MacGui: add a next and previous button to the summary panel preview.

This commit is contained in:
Damiano Galassi 2017-12-15 15:13:46 +01:00
parent b16949a1c1
commit dd89c106cf
No known key found for this signature in database
GPG Key ID: 27A26119422278AA
5 changed files with 326 additions and 46 deletions

View File

@ -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>

View 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">

View File

@ -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

View File

@ -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

View 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