]> granicus.if.org Git - handbrake/commitdiff
MacGui: add a next and previous button to the summary panel preview.
authorDamiano Galassi <damiog@gmail.com>
Fri, 15 Dec 2017 14:13:46 +0000 (15:13 +0100)
committerDamiano Galassi <damiog@gmail.com>
Fri, 15 Dec 2017 14:13:46 +0000 (15:13 +0100)
macosx/English.lproj/HBPreviewViewController.xib [new file with mode: 0644]
macosx/English.lproj/HBSummaryViewController.xib
macosx/HBPreviewViewController.h [new file with mode: 0644]
macosx/HBPreviewViewController.m [new file with mode: 0644]
macosx/HBSummaryViewController.m

diff --git a/macosx/English.lproj/HBPreviewViewController.xib b/macosx/English.lproj/HBPreviewViewController.xib
new file mode 100644 (file)
index 0000000..94364a9
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="HBPreviewViewController">
+            <connections>
+                <outlet property="hud" destination="Fn2-om-hEi" id="Fck-vd-r8e"/>
+                <outlet property="previewView" destination="wh8-oO-lCN" id="dCK-4h-Ho2"/>
+                <outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="Hz6-mo-xeY">
+            <rect key="frame" x="0.0" y="0.0" width="640" height="480"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <customView wantsLayer="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wh8-oO-lCN" customClass="HBPreviewView" propertyAccessControl="all">
+                    <rect key="frame" x="0.0" y="0.0" width="640" height="480"/>
+                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                </customView>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="Fn2-om-hEi" customClass="HBHUDView">
+                    <rect key="frame" x="280" y="40" width="80" height="26"/>
+                    <subviews>
+                        <button toolTip="Toggle Play/Pause" translatesAutoresizingMaskIntoConstraints="NO" id="5po-M6-Hqa">
+                            <rect key="frame" x="44" y="5" width="24" height="18"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="24" id="8M6-qp-Hbs"/>
+                                <constraint firstAttribute="height" constant="18" id="pHH-yR-lLG"/>
+                            </constraints>
+                            <buttonCell key="cell" type="square" title="›" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" id="Izx-9B-XA3">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system" size="18"/>
+                            </buttonCell>
+                            <accessibility description="Play/Pause"/>
+                            <connections>
+                                <action selector="next:" target="-2" id="IlJ-w9-A9q"/>
+                            </connections>
+                        </button>
+                        <button toolTip="Toggle Play/Pause" translatesAutoresizingMaskIntoConstraints="NO" id="1o6-MG-Jbu">
+                            <rect key="frame" x="12" y="6" width="24" height="16"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="16" id="efr-28-vaL"/>
+                                <constraint firstAttribute="width" constant="24" id="tBw-VV-Jdp"/>
+                            </constraints>
+                            <buttonCell key="cell" type="square" title="‹" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" id="EWx-of-C7c">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system" size="18"/>
+                            </buttonCell>
+                            <accessibility description="Play/Pause"/>
+                            <connections>
+                                <action selector="previous:" target="-2" id="UxL-j8-GeJ"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="1o6-MG-Jbu" firstAttribute="centerY" secondItem="5po-M6-Hqa" secondAttribute="centerY" id="aSW-vr-iFV"/>
+                        <constraint firstAttribute="trailing" secondItem="5po-M6-Hqa" secondAttribute="trailing" constant="12" id="esD-wC-uht"/>
+                        <constraint firstItem="5po-M6-Hqa" firstAttribute="leading" secondItem="1o6-MG-Jbu" secondAttribute="trailing" constant="8" id="gSU-gO-hbY"/>
+                        <constraint firstAttribute="height" constant="26" id="sJO-EZ-FmV"/>
+                        <constraint firstItem="1o6-MG-Jbu" firstAttribute="leading" secondItem="Fn2-om-hEi" secondAttribute="leading" constant="12" id="tO0-TJ-Bm0"/>
+                        <constraint firstItem="1o6-MG-Jbu" firstAttribute="top" secondItem="Fn2-om-hEi" secondAttribute="top" constant="4" id="ysh-ll-QCP"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstItem="Fn2-om-hEi" firstAttribute="centerX" secondItem="Hz6-mo-xeY" secondAttribute="centerX" id="1DU-Zn-HTj"/>
+                <constraint firstAttribute="bottom" secondItem="Fn2-om-hEi" secondAttribute="bottom" constant="40" id="M3h-dq-YzY"/>
+            </constraints>
+            <point key="canvasLocation" x="-376" y="-8"/>
+        </customView>
+    </objects>
+</document>
index 942816e26981778e9a8e5855d1ff2e076b7ec240..e7df77063b88cb7570d4706f2662b802bd269d4e 100644 (file)
@@ -1,9 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
         <deployment identifier="macosx"/>
-        <development version="8000" identifier="xcode"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13529"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -95,7 +94,7 @@
                         <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                     </textFieldCell>
                 </textField>
-                <customView wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="m5a-0z-QQ4" customClass="HBPreviewView">
+                <customView wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="m5a-0z-QQ4">
                     <rect key="frame" x="295" y="16" width="556" height="334"/>
                 </customView>
                 <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="Jgq-K8-z3W">
diff --git a/macosx/HBPreviewViewController.h b/macosx/HBPreviewViewController.h
new file mode 100644 (file)
index 0000000..d3101a5
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  HBPreviewViewController.h
+//  HandBrake
+//
+//  Created by Damiano Galassi on 14/12/2017.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@class HBPreviewGenerator;
+@class HBPreviewController;
+
+@interface HBPreviewViewController : NSViewController
+
+@property (nonatomic, readwrite, weak, nullable) HBPreviewGenerator *generator;
+
+- (void)update;
+
+@end
diff --git a/macosx/HBPreviewViewController.m b/macosx/HBPreviewViewController.m
new file mode 100644 (file)
index 0000000..a9e275e
--- /dev/null
@@ -0,0 +1,209 @@
+//
+//  HBPreviewViewController.m
+//  HandBrake
+//
+//  Created by Damiano Galassi on 14/12/2017.
+//
+
+#import <QuartzCore/QuartzCore.h>
+#import "HBPreviewViewController.h"
+
+#import "HBPreviewView.h"
+#import "HBPreviewGenerator.h"
+#import "HBPreviewController.h"
+
+@interface HBPreviewViewController ()
+
+@property (nonatomic, strong) IBOutlet HBPreviewView *previewView;
+
+@property (nonatomic, strong) IBOutlet NSView *hud;
+
+@property (nonatomic) NSInteger selectedIndex;
+@property (nonatomic) BOOL visible;
+
+@property (nonatomic) NSTimer *hudTimer;
+@property (nonatomic) BOOL mouseInView;
+
+@end
+
+@implementation HBPreviewViewController
+
+- (instancetype)init
+{
+    self = [super initWithNibName:@"HBPreviewViewController" bundle:nil];
+    if (self)
+    {
+        _selectedIndex = 1;
+    }
+    return self;
+}
+
+- (void)loadView
+{
+    [super loadView];
+    self.visible = YES;
+    self.previewView.showShadow = NO;
+
+    NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:self.view.frame
+                                                                options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways
+                                                                  owner:self
+                                                               userInfo:nil];
+    [self.view addTrackingArea:trackingArea];
+    self.hud.hidden = YES;
+    self.hud.layer.opacity = 0;
+}
+
+- (void)viewWillAppear
+{
+    self.visible = YES;
+    [self updatePicture];
+}
+
+- (void)viewDidDisappear
+{
+    self.visible = NO;
+}
+
+- (void)setGenerator:(HBPreviewGenerator *)generator
+{
+    _generator = generator;
+    if (generator)
+    {
+        self.selectedIndex = self.selectedIndex;
+        [self updatePicture];
+    }
+    else
+    {
+        self.previewView.image = nil;
+    }
+}
+
+- (void)update
+{
+    [self updatePicture];
+}
+
+#pragma MARK: - HUD
+
+- (void)mouseEntered:(NSEvent *)theEvent
+{
+    if (self.generator)
+    {
+        [self showHudWithAnimation:self.hud];
+    }
+    self.mouseInView = YES;
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent
+{
+    [super mouseMoved:theEvent];
+
+    // Test for mouse location to show/hide hud controls
+    if (self.generator && self.mouseInView)
+    {
+        [self showHudWithAnimation:self.hud];
+    }
+}
+
+- (void)mouseExited:(NSEvent *)theEvent
+{
+    [self hideHudWithAnimation:self.hud];
+    self.mouseInView = NO;
+}
+
+#define ANIMATION_DUR 0.15
+
+- (void)showHudWithAnimation:(NSView *)hud
+{
+    // The standard view animator doesn't play
+    // nicely with the Yosemite visual effects yet.
+    // So let's do the fade ourself.
+    if (hud.layer.opacity == 0 || hud.isHidden)
+    {
+        hud.hidden = NO;
+
+        [CATransaction begin];
+        CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        fadeInAnimation.fromValue = @(hud.layer.presentationLayer.opacity);
+        fadeInAnimation.toValue = @(1.0);
+        fadeInAnimation.beginTime = 0.0;
+        fadeInAnimation.duration = ANIMATION_DUR;
+
+        [hud.layer addAnimation:fadeInAnimation forKey:nil];
+        [hud.layer setOpacity:1];
+
+        [CATransaction commit];
+    }
+}
+
+- (void)hideHudWithAnimation:(NSView *)hud
+{
+    if (hud.layer.opacity != 0)
+    {
+        [CATransaction begin];
+        CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        fadeOutAnimation.fromValue = @(hud.layer.presentationLayer.opacity);
+        fadeOutAnimation.toValue = @(0.0);
+        fadeOutAnimation.beginTime = 0.0;
+        fadeOutAnimation.duration = ANIMATION_DUR;
+
+        [hud.layer addAnimation:fadeOutAnimation forKey:nil];
+        [hud.layer setOpacity:0];
+
+        [CATransaction commit];
+    }
+}
+
+#pragma MARK: - Preview index
+
+- (void)setSelectedIndex:(NSInteger)selectedIndex
+{
+    NSInteger count = self.generator.imagesCount;
+    if (selectedIndex >= count)
+    {
+        selectedIndex = count -1;
+    }
+    else if (selectedIndex < 0)
+    {
+        selectedIndex = 0;
+    }
+    _selectedIndex = selectedIndex;
+}
+
+- (IBAction)next:(id)sender
+{
+    self.selectedIndex += 1;
+    [self updatePicture];
+}
+
+- (IBAction)previous:(id)sender
+{
+    self.selectedIndex -= 1;
+    [self updatePicture];
+}
+
+- (void)updatePicture
+{
+    if (self.generator && self.visible)
+    {
+        CGImageRef fPreviewImage = [self.generator copyImageAtIndex:self.selectedIndex shouldCache:YES];
+        self.previewView.image = fPreviewImage;
+        CFRelease(fPreviewImage);
+    }
+}
+
+- (void)scrollWheel:(NSEvent *)theEvent
+{
+    if (theEvent.deltaY < 0)
+    {
+        self.selectedIndex += 1;
+        [self updatePicture];
+    }
+    else if (theEvent.deltaY > 0)
+    {
+        self.selectedIndex -= 1;
+        [self updatePicture];
+    }
+}
+
+@end
index e16f26e8729ed1fc541e30602438ce9b680eeb36..52c192172be5648c408355833b5cfd871c46ea8a 100644 (file)
@@ -5,7 +5,8 @@
  It may be used under the terms of the GNU General Public License. */
 
 #import "HBSummaryViewController.h"
-#import "HBPreviewView.h"
+
+#import "HBPreviewViewController.h"
 #import "HBPreviewGenerator.h"
 
 @import HandBrakeKit;
@@ -25,14 +26,14 @@ static void *HBSummaryViewControllerSubsContext = &HBSummaryViewControllerSubsCo
 @property (nonatomic, strong) IBOutlet NSTextField *filtersLabel;
 @property (nonatomic, strong) IBOutlet NSTextField *dimensionLabel;
 
-@property (nonatomic, strong) IBOutlet HBPreviewView *previewView;
+@property (nonatomic, strong) IBOutlet NSView *previewView;
+
+@property (nonatomic, strong) HBPreviewViewController *previewViewController;
 
 @property (nonatomic) BOOL tracksReloadInQueue;
 @property (nonatomic) BOOL filtersReloadInQueue;
 @property (nonatomic) BOOL pictureReloadInQueue;
 
-@property (nonatomic) BOOL visible;
-
 @end
 
 @implementation HBSummaryViewController
@@ -40,43 +41,25 @@ static void *HBSummaryViewControllerSubsContext = &HBSummaryViewControllerSubsCo
 - (instancetype)init
 {
     self = [super initWithNibName:@"HBSummaryViewController" bundle:nil];
+    if (self)
+    {
+        _previewViewController = [[HBPreviewViewController alloc] init];
+    }
     return self;
 }
 
 - (void)loadView
 {
     [super loadView];
-    self.previewView.showShadow = NO;
-    self.visible = YES;
+    self.previewViewController.view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
+    self.previewViewController.view.frame = NSMakeRect(0, 0, self.previewView.frame.size.width, self.previewView.frame.size.height);
+    [self.previewView addSubview:self.previewViewController.view];
     [self resetLabels];
 }
 
-- (void)viewWillAppear
-{
-    self.visible = YES;
-    if (self.pictureReloadInQueue || self.previewView.image == NULL)
-    {
-        [self updatePicture];
-    }
-}
-
-- (void)viewDidDisappear
-{
-    self.visible = NO;
-}
-
 - (void)setGenerator:(HBPreviewGenerator *)generator
 {
-    _generator = generator;
-
-    if (generator)
-    {
-        [self updatePicture];
-    }
-    else
-    {
-        self.previewView.image = nil;
-    }
+    self.previewViewController.generator = generator;
 }
 
 - (void)setJob:(HBJob *)job
@@ -258,7 +241,7 @@ static void *HBSummaryViewControllerSubsContext = &HBSummaryViewControllerSubsCo
     // to avoid reloading the same image multiple times.
     if (self.pictureReloadInQueue == NO)
     {
-        [[NSRunLoop mainRunLoop] performSelector:@selector(updatePicture) target:self argument:nil order:0 modes:@[NSDefaultRunLoopMode]];
+        [[NSRunLoop mainRunLoop] performSelector:@selector(updatePictureLabel) target:self argument:nil order:0 modes:@[NSDefaultRunLoopMode]];
         self.pictureReloadInQueue = YES;
     }
 }
@@ -285,18 +268,11 @@ static void *HBSummaryViewControllerSubsContext = &HBSummaryViewControllerSubsCo
     self.filtersReloadInQueue = NO;
 }
 
-- (void)updatePicture
+- (void)updatePictureLabel
 {
-    if (self.visible && self.generator)
-    {
-        NSUInteger index = self.generator.imagesCount > 1 ? 1 : 0;
-        CGImageRef fPreviewImage = [self.generator copyImageAtIndex:index shouldCache:NO];
-        self.previewView.image = fPreviewImage;
-        CFRelease(fPreviewImage);
-        self.pictureReloadInQueue = NO;
-
-        self.dimensionLabel.stringValue = self.job.picture.shortInfo;
-    }
+    self.pictureReloadInQueue = NO;
+    self.dimensionLabel.stringValue = self.job.picture.shortInfo;
+    [self.previewViewController update];
 }
 
 @end