Commit bfa68f6a authored by Alexandre Lision's avatar Alexandre Lision Committed by Alexandre Lision

ui: refactor preferences

- use a different window to display preferences. This allows proper window
resizing when switching between panels.
- remove the Setting button from the main interface (and the toolbar).

Issue: #80238
Change-Id: I220bfb3e92cdd426c721b3b5b1b44014a399fb48
parent 08abfacd
......@@ -77,8 +77,8 @@ SET(ringclient_CONTROLLERS
src/RingWizardWC.h
src/RingWindowController.mm
src/RingWindowController.h
src/PreferencesVC.mm
src/PreferencesVC.h
src/PreferencesWC.mm
src/PreferencesWC.h
src/AccGeneralVC.mm
src/AccGeneralVC.h
src/AccVideoVC.mm
......@@ -155,7 +155,7 @@ SET(ringclient_XIBS
AccSecurity
AudioPrefs
VideoPrefs
PreferencesScreen
PreferencesWindow
RingWizard
CertificateWindow
PersonLinker)
......
/*
* Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#import "PreferencesVC.h"
#import <QuartzCore/QuartzCore.h>
#import <accountmodel.h>
#import <audio/codecmodel.h>
#import "AccountsVC.h"
#import "GeneralPrefsVC.h"
#import "AudioPrefsVC.h"
#import "VideoPrefsVC.h"
#import "Constants.h"
@interface PreferencesVC ()
@property NSButton* toggleAdvancedSettings;
@end
@implementation PreferencesVC
@synthesize toggleAdvancedSettings;
static NSString* const kProfilePrefsIdentifier = @"ProfilesPrefsIdentifier";
static NSString* const kGeneralPrefsIdentifier = @"GeneralPrefsIdentifier";
static NSString* const kAudioPrefsIdentifer = @"AudioPrefsIdentifer";
static NSString* const kAncragePrefsIdentifer = @"AncragePrefsIdentifer";
static NSString* const kVideoPrefsIdentifer = @"VideoPrefsIdentifer";
static NSString* const kDonePrefsIdentifer = @"DonePrefsIdentifer";
static NSString* const kPowerSettingsIdentifer = @"PowerSettingsIdentifer";
-(void)loadView
{
[super loadView];
[self displayGeneral:nil];
[self.view setWantsLayer:YES];
self.view.layer.backgroundColor = [NSColor windowBackgroundColor].CGColor;
// Set the layer redraw policy. This would be better done in
// the initialization method of a NSView subclass instead of here.
self.view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
[self.view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
CGRect frame = CGRectOffset(self.view.frame, 0, -self.view.frame.size.height);
[CATransaction begin];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
animation.fromValue = @(frame.origin.y);
animation.toValue = @(self.view.frame.origin.y);
animation.duration = 0.3f;
[animation setTimingFunction:[CAMediaTimingFunction functionWithControlPoints:.7 :0.9 :1 :1]];
[self.view.layer addAnimation:animation forKey:animation.keyPath];
[CATransaction commit];
}
- (void) close
{
AccountModel::instance()->save();
CGRect frame = CGRectOffset(self.view.frame, 0, -self.view.frame.size.height);
[CATransaction begin];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
animation.fromValue = @(self.view.frame.origin.y);
animation.toValue = @(frame.origin.y);
animation.duration = 0.3f;
[animation setTimingFunction:[CAMediaTimingFunction functionWithControlPoints:.7 :0.9 :1 :1]];
[CATransaction setCompletionBlock:^{
[self.view removeFromSuperview];
}];
[self.view.layer addAnimation:animation forKey:animation.keyPath];
// set final layer position to prevent glitching back to original one
[self.view.layer setPosition:frame.origin];;
[CATransaction commit];
}
- (void)displayGeneral:(NSToolbarItem *)sender {
if (self.currentVC != nil) {
[self.currentVC.view removeFromSuperview];
}
self.generalPrefsVC = [[GeneralPrefsVC alloc] initWithNibName:@"GeneralPrefs" bundle:nil];
[self.view addSubview:self.generalPrefsVC.view];
[self.generalPrefsVC.view setFrame:[self.view bounds]];
self.currentVC = self.generalPrefsVC;
}
- (void)displayAudio:(NSToolbarItem *)sender {
if (self.currentVC != nil) {
[self.currentVC.view removeFromSuperview];
}
self.audioPrefsVC = [[AudioPrefsVC alloc] initWithNibName:@"AudioPrefs" bundle:nil];
[self.view addSubview:self.audioPrefsVC.view];
[self.audioPrefsVC.view setFrame:[self.view bounds]];
self.currentVC = self.audioPrefsVC;
}
- (void)displayAncrage:(NSToolbarItem *)sender {
}
- (void)displayVideo:(NSToolbarItem *)sender {
if (self.currentVC != nil) {
[self.currentVC.view removeFromSuperview];
}
self.videoPrefsVC = [[VideoPrefsVC alloc] initWithNibName:@"VideoPrefs" bundle:nil];
[self.view addSubview:self.videoPrefsVC.view];
[self.videoPrefsVC.view setFrame:[self.view bounds]];
self.currentVC = self.videoPrefsVC;
}
- (void) displayAccounts:(NSToolbarItem *) sender {
if (self.currentVC != nil) {
[self.currentVC.view removeFromSuperview];
}
self.accountsPrefsVC = [[AccountsVC alloc] initWithNibName:@"Accounts" bundle:nil];
[self.view addSubview:self.accountsPrefsVC.view];
[self.accountsPrefsVC.view setFrame:[self.view bounds]];
self.currentVC = self.accountsPrefsVC;
}
#pragma NSToolbar Delegate
-(NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
NSToolbarItem* item = nil;
if ([itemIdentifier isEqualToString: kProfilePrefsIdentifier]) {
item = [[NSToolbarItem alloc] initWithItemIdentifier: kProfilePrefsIdentifier];
[item setImage: [NSImage imageNamed: @"NSUserAccounts"]];
[item setLabel: @"Accounts"];
[item setAction:@selector(displayAccounts:)];
}
if ([itemIdentifier isEqualToString: kGeneralPrefsIdentifier]) {
item = [[NSToolbarItem alloc] initWithItemIdentifier: kGeneralPrefsIdentifier];
[item setImage: [NSImage imageNamed: @"general"]];
[item setLabel: @"General"];
[item setAction:@selector(displayGeneral:)];
}
if ([itemIdentifier isEqualToString: kAudioPrefsIdentifer]) {
item = [[NSToolbarItem alloc] initWithItemIdentifier: kAudioPrefsIdentifer];
[item setImage: [NSImage imageNamed: @"audio"]];
[item setLabel: @"Audio"];
[item setAction:@selector(displayAudio:)];
}
if ([itemIdentifier isEqualToString: kPowerSettingsIdentifer]) {
item = [[NSToolbarItem alloc] initWithItemIdentifier: kPowerSettingsIdentifer];
toggleAdvancedSettings = [[NSButton alloc] initWithFrame:NSMakeRect(0,0,20,20)];
[toggleAdvancedSettings setButtonType:NSSwitchButton];
[toggleAdvancedSettings setTitle:@""];
[toggleAdvancedSettings setState:[[NSUserDefaults standardUserDefaults] boolForKey:Preferences::ShowAdvanced]];
[item setLabel:@"Show Advanced"];
[item setView:toggleAdvancedSettings];
[item setAction:@selector(togglePowerSettings:)];
}
if ([itemIdentifier isEqualToString: kDonePrefsIdentifer]) {
item = [[NSToolbarItem alloc] initWithItemIdentifier: kDonePrefsIdentifer];
[item setImage: [NSImage imageNamed: @"ic_action_cancel"]];
[item setLabel: @"Done"];
[item setAction:@selector(closePreferences:)];
}
if ([itemIdentifier isEqualToString: kVideoPrefsIdentifer]) {
item = [[NSToolbarItem alloc] initWithItemIdentifier: kVideoPrefsIdentifer];
[item setImage: [NSImage imageNamed: @"video"]];
[item setLabel: @"Video"];
[item setAction:@selector(displayVideo:)];
}
return item;
}
-(NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
{
NSMutableArray* items = [NSMutableArray arrayWithObjects:
kPowerSettingsIdentifer,
NSToolbarFlexibleSpaceItemIdentifier,
kGeneralPrefsIdentifier,
kAudioPrefsIdentifer,
kVideoPrefsIdentifer,
// kAncragePrefsIdentifer,
NSToolbarFlexibleSpaceItemIdentifier,
kDonePrefsIdentifer,
nil];
if([[NSUserDefaults standardUserDefaults] boolForKey:Preferences::ShowAdvanced]) {
[items insertObject:NSToolbarSpaceItemIdentifier atIndex:5];
[items insertObject:kProfilePrefsIdentifier atIndex:2];
} else
[items insertObject:NSToolbarSpaceItemIdentifier atIndex:5];
return items;
}
-(NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar
{
NSMutableArray* items = [NSMutableArray arrayWithObjects:
kPowerSettingsIdentifer,
kGeneralPrefsIdentifier,
kAudioPrefsIdentifer,
kVideoPrefsIdentifer,
nil];
if([[NSUserDefaults standardUserDefaults] boolForKey:Preferences::ShowAdvanced])
[items insertObject:kProfilePrefsIdentifier atIndex:1];
return items;
}
-(NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
{
return nil;
}
@end
/*
* Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
* Copyright (C) 2015 Savoir-faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
......@@ -15,38 +15,14 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#ifndef PREFERENCESVIEWCONTROLLER_H
#define PREFERENCESVIEWCONTROLLER_H
#import <Cocoa/Cocoa.h>
@interface PreferencesVC : NSViewController <NSToolbarDelegate>
@interface PreferencesWC : NSWindowController <NSWindowDelegate>
@property (nonatomic, strong) NSViewController *currentVC;
@property (nonatomic, strong) NSViewController *accountsPrefsVC;
@property (nonatomic, strong) NSViewController *generalPrefsVC;
@property (nonatomic, strong) NSViewController *audioPrefsVC;
@property (nonatomic, strong) NSViewController *videoPrefsVC;
- (void) close;
- (void)displayGeneral:(NSToolbarItem *)sender;
- (void)displayAudio:(NSToolbarItem *)sender;
- (void)displayAncrage:(NSToolbarItem *)sender;
- (void)displayVideo:(NSToolbarItem *)sender;
- (void)displayAccounts:(NSToolbarItem *)sender;
@end
#endif // PREFERENCESVIEWCONTROLLER_H
\ No newline at end of file
/*
* Copyright (C) 2015 Savoir-faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import "PreferencesWC.h"
#import <QuartzCore/QuartzCore.h>
#import <accountmodel.h>
#import <audio/codecmodel.h>
#import "AccountsVC.h"
#import "GeneralPrefsVC.h"
#import "AudioPrefsVC.h"
#import "VideoPrefsVC.h"
#import "Constants.h"
@implementation PreferencesWC {
__unsafe_unretained IBOutlet NSView *prefsContainer;
NSViewController *currentVC;
}
static NSString* const kProfilePrefsIdentifier = @"AccountsPrefsIdentifier";
static NSString* const kGeneralPrefsIdentifier = @"GeneralPrefsIdentifier";
static NSString* const kAudioPrefsIdentifer = @"AudioPrefsIdentifer";
static NSString* const kVideoPrefsIdentifer = @"VideoPrefsIdentifer";
- (void)windowDidLoad
{
[super windowDidLoad];
[self.window setMovableByWindowBackground:YES];
[self.window.toolbar setSelectedItemIdentifier:kGeneralPrefsIdentifier];
[self displayGeneral:nil];
}
- (void)windowWillClose:(NSNotification *)notification
{
AccountModel::instance()->save();
}
- (IBAction)displayGeneral:(NSToolbarItem *)sender
{
[[prefsContainer subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
currentVC = [[GeneralPrefsVC alloc] initWithNibName:@"GeneralPrefs" bundle:nil];
[self resizeWindowWithFrame:currentVC.view.frame];
[prefsContainer addSubview:currentVC.view];
}
- (IBAction)displayAudio:(NSToolbarItem *)sender
{
[[prefsContainer subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
currentVC = [[AudioPrefsVC alloc] initWithNibName:@"AudioPrefs" bundle:nil];
[self resizeWindowWithFrame:currentVC.view.frame];
[prefsContainer addSubview:currentVC.view];
}
- (IBAction)displayVideo:(NSToolbarItem *)sender
{
[[prefsContainer subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
currentVC = [[VideoPrefsVC alloc] initWithNibName:@"VideoPrefs" bundle:nil];
[self resizeWindowWithFrame:currentVC.view.frame];
[prefsContainer addSubview:currentVC.view];
}
- (IBAction)displayAccounts:(NSToolbarItem *)sender
{
[[prefsContainer subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
currentVC = [[AccountsVC alloc] initWithNibName:@"Accounts" bundle:nil];
[self resizeWindowWithFrame:currentVC.view.frame];
[prefsContainer addSubview:currentVC.view];
}
- (void) resizeWindowWithFrame:(NSRect)fr
{
NSToolbar *toolbar = [self.window toolbar];
CGFloat toolbarHeight = 0.0;
NSRect windowFrame;
if (toolbar && [toolbar isVisible]) {
windowFrame = [NSWindow contentRectForFrameRect:[self.window frame]
styleMask:[self.window styleMask]];
toolbarHeight = NSHeight(windowFrame) - NSHeight([[self.window contentView] frame]);
}
auto frame = [self.window frame];
frame.origin.y += frame.size.height;
frame.origin.y -= NSHeight(fr) + toolbarHeight;
frame.size.height = NSHeight(fr) + toolbarHeight;
frame.size.width = NSWidth(fr);
frame = [NSWindow frameRectForContentRect:frame
styleMask:[self.window styleMask]];
[self.window setFrame:frame display:YES animate:YES];
}
@end
......@@ -171,7 +171,7 @@
&QAbstractItemModel::rowsMoved,
[self](const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow) {
for( int row = sourceStart; row <= sourceEnd; row++) {
NSIndexPath* srcPath = [self qIdxToNSIndexPath:self->privateQModel->index(sourceStart, 0, sourceParent)];
NSIndexPath* srcPath = [self qIdxToNSIndexPath:self->privateQModel->index(row, 0, sourceParent)];
NSIndexPath* destPath = [self qIdxToNSIndexPath:self->privateQModel->index(destinationRow, 0, destinationParent)];
[self moveNode:[self.arrangedObjects descendantNodeAtIndexPath:srcPath] toIndexPath:destPath];
......
......@@ -18,15 +18,11 @@
*/
#import <Cocoa/Cocoa.h>
#import "HistoryVC.h"
#import "PreferencesVC.h"
@interface RingWindowController : NSWindowController <NSToolbarDelegate, NSTextFieldDelegate>{
@interface RingWindowController : NSWindowController {
IBOutlet NSView *currentView;
}
@property (nonatomic, assign) NSViewController *myCurrentViewController;
@property PreferencesVC* preferencesViewController;
- (IBAction)openPreferences:(id)sender;
- (IBAction)closePreferences:(NSToolbarItem *)sender;
@end
......@@ -28,32 +28,29 @@
#import "Constants.h"
#import "CurrentCallVC.h"
#import "PreferencesWC.h"
#import "views/NSColor+RingTheme.h"
@interface RingWindowController ()
@implementation RingWindowController {
@property CurrentCallVC* currentVC;
@property (unsafe_unretained) IBOutlet NSView *callView;
@property (unsafe_unretained) IBOutlet NSTextField *ringIDLabel;
__unsafe_unretained IBOutlet NSView *callView;
__unsafe_unretained IBOutlet NSTextField *ringIDLabel;
@end
@implementation RingWindowController
@synthesize currentVC;
@synthesize callView, ringIDLabel;
PreferencesWC *preferencesWC;
CurrentCallVC* currentVC;
}
static NSString* const kPreferencesIdentifier = @"PreferencesIdentifier";
- (void)windowDidLoad {
[super windowDidLoad];
[self.window setMovableByWindowBackground:YES];
[self displayMainToolBar];
currentVC = [[CurrentCallVC alloc] initWithNibName:@"CurrentCall" bundle:nil];
[callView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[[currentVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[callView addSubview:[self.currentVC view] positioned:NSWindowAbove relativeTo:nil];
[callView addSubview:[currentVC view] positioned:NSWindowAbove relativeTo:nil];
[currentVC initFrame];
......@@ -99,149 +96,8 @@ static NSString* const kPreferencesIdentifier = @"PreferencesIdentifier";
- (IBAction)openPreferences:(id)sender
{
if(self.preferencesViewController != nil) {
[self closePreferences:nil];
return;
}
NSToolbar* tb = [[NSToolbar alloc] initWithIdentifier: @"PreferencesToolbar"];
self.preferencesViewController = [[PreferencesVC alloc] initWithNibName:@"PreferencesScreen" bundle:nil];
self.myCurrentViewController = self.preferencesViewController;
NSLayoutConstraint* test = [NSLayoutConstraint constraintWithItem:self.preferencesViewController.view
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:currentView
attribute:NSLayoutAttributeWidth
multiplier:1.0f
constant:0.0f];
NSLayoutConstraint* test2 = [NSLayoutConstraint constraintWithItem:self.preferencesViewController.view
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:currentView
attribute:NSLayoutAttributeHeight
multiplier:1.0f
constant:0.0f];
NSLayoutConstraint* test3 = [NSLayoutConstraint constraintWithItem:self.preferencesViewController.view
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:currentView
attribute:NSLayoutAttributeCenterX
multiplier:1.0f
constant:0.0f];
[currentView addSubview:[self.preferencesViewController view]];
[tb setDelegate: self.preferencesViewController];
[self.window setToolbar: tb];
[self.window.toolbar setSelectedItemIdentifier:@"GeneralPrefsIdentifier"];
[currentView addConstraint:test];
[currentView addConstraint:test2];
[currentView addConstraint:test3];
// make sure we automatically resize the controller's view to the current window size
[[self.myCurrentViewController view] setFrame:[currentView bounds]];
// set the view controller's represented object to the number of subviews in that controller
// (our NSTextField's value binding will reflect this value)
[self.myCurrentViewController setRepresentedObject:[NSNumber numberWithUnsignedInteger:[[[self.myCurrentViewController view] subviews] count]]];
}
- (IBAction) closePreferences:(NSToolbarItem *)sender {
if(self.myCurrentViewController != nil)
{
[self.preferencesViewController close];
[self displayMainToolBar];
self.preferencesViewController = nil;
}
}
-(void) displayMainToolBar
{
NSToolbar* tb = [[NSToolbar alloc] initWithIdentifier: @"MainToolbar"];
[tb setDisplayMode:NSToolbarDisplayModeIconAndLabel];
[tb setDelegate: self];
[self.window setToolbar: tb];
}
// FIXME: This is sick, NSWindowController is catching my selectors
- (void)displayGeneral:(NSToolbarItem *)sender {
[self.preferencesViewController displayGeneral:sender];
}
- (void)displayAudio:(NSToolbarItem *)sender {
[self.preferencesViewController displayAudio:sender];
}
- (void)displayAncrage:(NSToolbarItem *)sender {
[self.preferencesViewController displayAncrage:sender];
}
- (void)displayVideo:(NSToolbarItem *)sender {
[self.preferencesViewController displayVideo:sender];
}
- (void)displayAccounts:(NSToolbarItem *)sender {