mirror of
https://github.com/zakk4223/CocoaSplit.git
synced 2026-05-15 14:15:50 -06:00
487 lines
15 KiB
Objective-C
487 lines
15 KiB
Objective-C
//
|
|
// InputPopupControllerViewController.m
|
|
// CocoaSplit
|
|
//
|
|
// Created by Zakk on 7/26/14.
|
|
// Copyright (c) 2014 Zakk. All rights reserved.
|
|
//
|
|
|
|
#import "InputPopupControllerViewController.h"
|
|
#import "InputSource.h"
|
|
#import "CSCIFilterConfigProxy.h"
|
|
#import "CSFilterChooserWindowController.h"
|
|
#import "SourceLayout.h"
|
|
|
|
@interface InputPopupControllerViewController ()
|
|
|
|
@end
|
|
|
|
@implementation InputPopupControllerViewController
|
|
@synthesize inputSource = _inputSource;
|
|
|
|
|
|
-(instancetype) init
|
|
{
|
|
if (self = [super init])
|
|
{
|
|
self = [super initWithNibName:@"InputPopupControllerViewController" bundle:nil];
|
|
self.inputConstraintMap = @{@"Left Edge": @(kCAConstraintMinX),
|
|
@"Right Edge": @(kCAConstraintMaxX),
|
|
@"Top Edge": @(kCAConstraintMaxY),
|
|
@"Bottom Edge": @(kCAConstraintMinY),
|
|
@"Horizontal Center": @(kCAConstraintMidX),
|
|
@"Vertical Center": @(kCAConstraintMidY),
|
|
@"Width": @(kCAConstraintWidth),
|
|
@"Height": @(kCAConstraintHeight),
|
|
};
|
|
|
|
self.constraintSortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:@"value" ascending:YES]];
|
|
self.availableTransitions = [NSMutableDictionary dictionary];
|
|
|
|
NSArray *caTransitionNames = @[kCATransitionFade, kCATransitionPush, kCATransitionMoveIn, kCATransitionReveal, @"cube", @"alignedCube", @"flip", @"alignedFlip"];
|
|
NSArray *ciTransitionNames = [CIFilter filterNamesInCategory:kCICategoryTransition];
|
|
|
|
for (NSString *caName in caTransitionNames)
|
|
{
|
|
[self.availableTransitions setObject:caName forKey:caName];
|
|
}
|
|
|
|
for (NSString *ciName in ciTransitionNames)
|
|
{
|
|
NSString *niceName = [CIFilter localizedNameForFilterName:ciName];
|
|
[self.availableTransitions setObject:niceName forKey:ciName];
|
|
}
|
|
|
|
self.compositionFilterNames = [CIFilter filterNamesInCategory:kCICategoryCompositeOperation];
|
|
|
|
|
|
//self = [super initWithNibName:@"TestView" bundle:nil];
|
|
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
+(NSSet *)keyPathsForValuesAffectingSelectedVideoType
|
|
{
|
|
return [NSSet setWithObjects:@"inputSource", nil];
|
|
}
|
|
|
|
|
|
-(void)setInputSource:(InputSource *)inputSource
|
|
{
|
|
_inputSource = inputSource;
|
|
|
|
[self sourceConfigurationView];
|
|
|
|
}
|
|
|
|
-(InputSource *)inputSource
|
|
{
|
|
return _inputSource;
|
|
}
|
|
|
|
|
|
-(NSString *)selectedVideoType
|
|
{
|
|
|
|
return self.inputSource.selectedVideoType;
|
|
}
|
|
|
|
-(IBAction) configureInputTransition:(NSButton *)sender
|
|
{
|
|
if (self.inputSource.advancedTransition)
|
|
{
|
|
[self openTransitionFilterPanel:self.inputSource.advancedTransition];
|
|
}
|
|
}
|
|
|
|
|
|
- (IBAction)configureFilter:(NSButton *)sender
|
|
{
|
|
CIFilter *selectedFilter;
|
|
CALayer *useLayer = nil;
|
|
|
|
NSString *filterType = @"filters";
|
|
|
|
if (sender.tag == 1)
|
|
{
|
|
selectedFilter = [self.inputSource.layer.backgroundFilters objectAtIndex:self.backgroundFilterTableView.selectedRow];
|
|
useLayer = self.inputSource.layer;
|
|
filterType = @"backgroundFilters";
|
|
} else if (sender.tag == 2) {
|
|
|
|
selectedFilter = [self.inputSource.layer.sourceLayer.filters objectAtIndex:self.sourceFilterTableView.selectedRow];
|
|
useLayer = self.inputSource.layer.sourceLayer;
|
|
} else if (sender.tag == 3) {
|
|
selectedFilter = [self.inputSource.layer.filters objectAtIndex:self.layerFilterTableView.selectedRow];
|
|
useLayer = self.inputSource.layer;
|
|
}
|
|
|
|
if (selectedFilter)
|
|
{
|
|
[self openUserFilterPanel:selectedFilter forLayer:useLayer withType:filterType];
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- (IBAction)removeFilter:(NSButton *)sender
|
|
{
|
|
CIFilter *selectedFilter;
|
|
|
|
|
|
if (sender.tag == 1)
|
|
{
|
|
selectedFilter = [self.inputSource.layer.backgroundFilters objectAtIndex:self.backgroundFilterTableView.selectedRow];
|
|
[self.inputSource deleteBackgroundFilter:selectedFilter.name];
|
|
|
|
} else if (sender.tag == 2) {
|
|
|
|
selectedFilter = [self.inputSource.layer.sourceLayer.filters objectAtIndex:self.sourceFilterTableView.selectedRow];
|
|
[self.inputSource deleteSourceFilter:selectedFilter.name];
|
|
|
|
} else if (sender.tag == 3) {
|
|
selectedFilter = [self.inputSource.layer.filters objectAtIndex:self.layerFilterTableView.selectedRow];
|
|
[self.inputSource deleteLayerFilter:selectedFilter.name];
|
|
}
|
|
}
|
|
|
|
|
|
-(void)setSelectedVideoType:(NSString *)selectedVideoType
|
|
{
|
|
self.inputSource.selectedVideoType = selectedVideoType;
|
|
[self sourceConfigurationView];
|
|
}
|
|
|
|
|
|
-(void)sourceConfigurationView
|
|
{
|
|
|
|
self.inputConfigViewController = [self.inputSource sourceConfigurationView];
|
|
|
|
|
|
NSView *configView = self.inputConfigViewController.view;
|
|
self.view.hidden = NO;
|
|
|
|
|
|
NSArray *currentSubviews = self.sourceConfigView.subviews;
|
|
NSView *currentSubview = currentSubviews.firstObject;
|
|
|
|
|
|
if (!configView)
|
|
{
|
|
[currentSubview removeFromSuperview];
|
|
} else if (currentSubview) {
|
|
[[self.sourceConfigView animator] replaceSubview:currentSubview with:configView ];
|
|
[configView setFrameOrigin:NSMakePoint(configView.frame.origin.x, NSMaxY(self.sourceConfigView.frame) - configView.frame.size.height)];
|
|
|
|
} else {
|
|
[[self.sourceConfigView animator] addSubview:configView];
|
|
[configView setFrameOrigin:NSMakePoint(configView.frame.origin.x, NSMaxY(self.sourceConfigView.frame) - configView.frame.size.height)];
|
|
}
|
|
|
|
}
|
|
|
|
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
|
|
{
|
|
|
|
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
|
if (self) {
|
|
// Initialization code here.
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)popoverDidClose:(NSNotification *)notification
|
|
{
|
|
|
|
NSString *closeReason = [[notification userInfo] valueForKey:NSPopoverCloseReasonKey];
|
|
|
|
if (closeReason && closeReason == NSPopoverCloseReasonStandard)
|
|
{
|
|
// closeReason can be:
|
|
// NSPopoverCloseReasonStandard
|
|
// NSPopoverCloseReasonDetachToWindow
|
|
//
|
|
// add new code here if you want to respond "after" the popover closes
|
|
//
|
|
self.inputSource.editorController = nil;
|
|
}
|
|
|
|
[self.inputSource editorPopoverDidClose];
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
-(NSString *)bindKeyForAffineTransform:(NSObject *)transform withProxy:(CSCIFilterConfigProxy *)withProxy
|
|
{
|
|
NSString *baseBinding = nil;
|
|
|
|
for (NSString *bindkey in transform.exposedBindings)
|
|
{
|
|
if ([bindkey isEqualToString:@"affineTransform"])
|
|
{
|
|
NSDictionary *bindInfo = [transform infoForBinding:bindkey];
|
|
NSString *bindpath = bindInfo[NSObservedKeyPathKey];
|
|
if (bindpath && [bindpath hasPrefix:@"selection."])
|
|
{
|
|
baseBinding = [bindpath substringFromIndex:@"selection.".length];
|
|
[transform unbind:bindkey];
|
|
[transform bind:bindkey toObject:withProxy withKeyPath:[NSString stringWithFormat:@"baseDict.%@",baseBinding] options:bindInfo[NSOptionsKey]];
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return baseBinding;
|
|
}
|
|
-(NSString *)bindKeyForVector:(NSObject *)vector withProxy:(CSCIFilterConfigProxy *)withProxy
|
|
{
|
|
NSString *baseBinding = nil;
|
|
|
|
for (NSString *bindkey in vector.exposedBindings)
|
|
{
|
|
if ([bindkey isEqualToString:@"vector"])
|
|
{
|
|
NSDictionary *bindInfo = [vector infoForBinding:bindkey];
|
|
NSString *bindpath = bindInfo[NSObservedKeyPathKey];
|
|
if (bindpath && [bindpath hasPrefix:@"selection."])
|
|
{
|
|
baseBinding = [bindpath substringFromIndex:@"selection.".length];
|
|
[vector unbind:bindkey];
|
|
[vector bind:bindkey toObject:withProxy withKeyPath:[NSString stringWithFormat:@"baseDict.%@",baseBinding] options:bindInfo[NSOptionsKey]];
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return baseBinding;
|
|
}
|
|
|
|
-(void)rebindViewControls:(NSView *)forView withProxy:(CSCIFilterConfigProxy *)withProxy
|
|
{
|
|
for (NSString *b in forView.exposedBindings)
|
|
{
|
|
|
|
NSDictionary *bindingInfo = [forView infoForBinding:b];
|
|
|
|
|
|
if (!bindingInfo)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
NSDictionary *bindingOptions = bindingInfo[NSOptionsKey];
|
|
|
|
NSString *bindPath = bindingInfo[NSObservedKeyPathKey];
|
|
|
|
NSObject *boundTo = bindingInfo[NSObservedObjectKey];
|
|
|
|
|
|
NSString *baseBinding;
|
|
|
|
|
|
if ([bindPath hasPrefix:@"selection."])
|
|
{
|
|
baseBinding = [bindPath substringFromIndex:@"selection.".length];
|
|
[forView unbind:b];
|
|
[forView bind:b toObject:withProxy withKeyPath:[NSString stringWithFormat:@"baseDict.%@",baseBinding] options:bindingOptions];
|
|
|
|
} else if ([boundTo.className isEqualToString:@"CIMutableVector"]) {
|
|
[self bindKeyForVector:boundTo withProxy:withProxy];
|
|
} else if ([boundTo.className isEqualToString:@"NSMutableAffineTransform"]) {
|
|
[self bindKeyForAffineTransform:boundTo withProxy:withProxy];
|
|
|
|
}
|
|
}
|
|
|
|
for (NSView *subview in forView.subviews)
|
|
{
|
|
[self rebindViewControls:subview withProxy:withProxy];
|
|
|
|
}
|
|
|
|
|
|
}
|
|
-(void)openUserFilterPanel:(CIFilter *)forFilter forLayer:(CALayer *)forLayer withType:(NSString *)withType
|
|
{
|
|
if (!forFilter)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CSCIFilterConfigProxy *filterProxy = [[CSCIFilterConfigProxy alloc] init];
|
|
|
|
|
|
filterProxy.baseLayer = forLayer;
|
|
filterProxy.layerFilterName = forFilter.name;
|
|
filterProxy.filterType = withType;
|
|
|
|
|
|
IKFilterUIView *filterView = [forFilter viewForUIConfiguration:@{IKUISizeFlavor:IKUISizeMini} excludedKeys:@[kCIInputImageKey, kCIInputTargetImageKey, kCIInputTimeKey]];
|
|
|
|
|
|
|
|
if (forLayer)
|
|
{
|
|
CSCIFilterConfigProxy *filterProxy = [[CSCIFilterConfigProxy alloc] init];
|
|
filterProxy.baseLayer = forLayer;
|
|
filterProxy.layerFilterName = forFilter.name;
|
|
filterProxy.filterType = withType;
|
|
|
|
[self rebindViewControls:filterView withProxy:filterProxy];
|
|
}
|
|
|
|
|
|
self.userFilterWindow = [[NSWindow alloc] init];
|
|
|
|
self.userFilterWindow.delegate = self;
|
|
[self.userFilterWindow setContentSize:filterView.bounds.size];
|
|
[self.userFilterWindow.contentView addSubview:filterView];
|
|
self.userFilterWindow.styleMask = NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask;
|
|
[self.userFilterWindow setReleasedWhenClosed:NO];
|
|
|
|
[self.userFilterWindow makeKeyAndOrderFront:self.userFilterWindow];
|
|
|
|
}
|
|
|
|
- (IBAction)addFilterAction:(NSButton *)sender
|
|
{
|
|
NSString *filterName = [CSFilterChooserWindowController run];
|
|
|
|
if (sender.tag == 1)
|
|
{
|
|
[self.inputSource addBackgroundFilter:filterName];
|
|
} else if (sender.tag == 2) {
|
|
[self.inputSource addSourceFilter:filterName];
|
|
} else if (sender.tag == 3) {
|
|
[self.inputSource addLayerFilter:filterName];
|
|
}
|
|
}
|
|
|
|
|
|
-(void)tableViewSelectionDidChange:(NSNotification *)notification
|
|
{
|
|
NSTableView *tableView = notification.object;
|
|
|
|
if (tableView == self.backgroundFilterTableView)
|
|
{
|
|
if (tableView.selectedRow > -1)
|
|
{
|
|
self.backgroundTableHasSelection = YES;
|
|
} else {
|
|
self.backgroundTableHasSelection = NO;
|
|
}
|
|
} else if (tableView == self.sourceFilterTableView) {
|
|
if (tableView.selectedRow > -1)
|
|
{
|
|
self.sourceTableHasSelection = YES;
|
|
} else {
|
|
self.sourceTableHasSelection = NO;
|
|
}
|
|
|
|
} else if (tableView == self.layerFilterTableView) {
|
|
if (tableView.selectedRow > -1)
|
|
{
|
|
self.layerTableHasSelection = YES;
|
|
} else {
|
|
self.layerTableHasSelection = NO;
|
|
}
|
|
}
|
|
}
|
|
|
|
-(void)openTransitionFilterPanel:(CIFilter *)forFilter
|
|
{
|
|
if (!forFilter)
|
|
{
|
|
return;
|
|
}
|
|
|
|
IKFilterUIView *filterView = [forFilter viewForUIConfiguration:@{IKUISizeFlavor:IKUISizeMini} excludedKeys:@[kCIInputImageKey, kCIInputTargetImageKey, kCIInputTimeKey]];
|
|
|
|
|
|
self.transitionFilterWindow = [[NSWindow alloc] init];
|
|
self.transitionFilterWindow.delegate = self;
|
|
[self.transitionFilterWindow setContentSize:filterView.bounds.size];
|
|
[self.transitionFilterWindow.contentView addSubview:filterView];
|
|
|
|
self.transitionFilterWindow.styleMask = NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask;
|
|
[self.transitionFilterWindow setReleasedWhenClosed:NO];
|
|
|
|
[self.transitionFilterWindow makeKeyAndOrderFront:self.transitionFilterWindow];
|
|
|
|
}
|
|
|
|
|
|
|
|
-(IBAction) clearGradient:(NSButton *)sender
|
|
{
|
|
|
|
[self.undoManager beginUndoGrouping];
|
|
self.inputSource.startColor = nil;
|
|
self.inputSource.stopColor = nil;
|
|
[self.undoManager setActionName:@"Clear Gradient"];
|
|
[self.undoManager endUndoGrouping];
|
|
}
|
|
|
|
|
|
|
|
- (IBAction)resetConstraints:(id)sender
|
|
{
|
|
NSDictionary *oldConstraints = self.inputSource.constraintMap;
|
|
|
|
[[self.inputSource.sourceLayout.undoManager prepareWithInvocationTarget:self.inputSource.sourceLayout] modifyUUID:self.inputSource.uuid withBlock:^(InputSource *input) {
|
|
|
|
input.constraintMap = oldConstraints;
|
|
}];
|
|
|
|
|
|
[self.inputSource resetConstraints];
|
|
|
|
}
|
|
|
|
- (IBAction)deleteMultiSource:(id)sender
|
|
{
|
|
|
|
NSTableView *bTable = (NSTableView *)sender;
|
|
NSInteger deleteRow = [bTable clickedRow];
|
|
|
|
InputSource *toConfig = [self.multiSourceController.arrangedObjects objectAtIndex:deleteRow];
|
|
|
|
|
|
InputPopupControllerViewController *windowController = [[InputPopupControllerViewController alloc] init];
|
|
|
|
windowController.inputSource = toConfig;
|
|
NSWindow *configWindow = [[NSWindow alloc] init];
|
|
|
|
NSRect newFrame = [configWindow frameRectForContentRect:NSMakeRect(0.0f, 0.0f, windowController.view.frame.size.width, windowController.view.frame.size.height)];
|
|
|
|
[configWindow setFrame:newFrame display:NO];
|
|
|
|
[configWindow setReleasedWhenClosed:NO];
|
|
|
|
|
|
[configWindow.contentView addSubview:windowController.view];
|
|
configWindow.title = [NSString stringWithFormat:@"CocoaSplit Input (%@)", windowController.inputSource.name];
|
|
configWindow.delegate = windowController.inputSource;
|
|
|
|
configWindow.styleMask = NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask;
|
|
|
|
windowController.inputSource.editorWindow = configWindow;
|
|
windowController.inputSource.editorController = windowController;
|
|
[configWindow makeKeyAndOrderFront:NSApp];
|
|
}
|
|
|
|
|
|
@end
|