Merge pull request #64 in ITERATE/cyberduck from feature/windows/9074 to master
[cyberduck.git] / source / ch / cyberduck / ui / cocoa / WindowController.java
blob2adc965d92ea1c8f2992bfa78ca16d1285fa331e
1 package ch.cyberduck.ui.cocoa;
3 /*
4 * Copyright (c) 2005 David Kocher. All rights reserved.
5 * http://cyberduck.ch/
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * Bug fixes, suggestions and comments should be sent to:
18 * dkocher@cyberduck.ch
21 import ch.cyberduck.binding.application.NSAlert;
22 import ch.cyberduck.binding.application.NSButton;
23 import ch.cyberduck.binding.application.NSCell;
24 import ch.cyberduck.binding.application.NSPrintInfo;
25 import ch.cyberduck.binding.application.NSPrintOperation;
26 import ch.cyberduck.binding.application.NSPrintPanel;
27 import ch.cyberduck.binding.application.NSTextField;
28 import ch.cyberduck.binding.application.NSTextView;
29 import ch.cyberduck.binding.application.NSView;
30 import ch.cyberduck.binding.application.NSWindow;
31 import ch.cyberduck.binding.application.SheetCallback;
32 import ch.cyberduck.binding.foundation.NSAttributedString;
33 import ch.cyberduck.binding.foundation.NSDictionary;
34 import ch.cyberduck.binding.foundation.NSNotification;
35 import ch.cyberduck.core.Host;
36 import ch.cyberduck.core.LocaleFactory;
37 import ch.cyberduck.core.exception.BackgroundException;
38 import ch.cyberduck.core.local.BrowserLauncherFactory;
39 import ch.cyberduck.core.preferences.PreferencesFactory;
40 import ch.cyberduck.ui.cocoa.threading.PanelAlertCallback;
42 import org.apache.commons.lang3.StringUtils;
43 import org.apache.log4j.Logger;
44 import org.rococoa.Foundation;
45 import org.rococoa.ID;
46 import org.rococoa.cocoa.foundation.NSPoint;
48 import java.util.Collections;
49 import java.util.HashSet;
50 import java.util.Set;
52 /**
53 * @version $Id$
55 public abstract class WindowController extends BundleController implements NSWindow.Delegate {
56 private static Logger log = Logger.getLogger(WindowController.class);
58 protected static final String DEFAULT = LocaleFactory.localizedString("Default");
60 public WindowController() {
61 super();
64 @Override
65 public void invalidate() {
66 listeners.clear();
67 if(window != null) {
68 window.setDelegate(null);
70 super.invalidate();
73 /**
74 * The window this controller is owner of
76 @Outlet
77 protected NSWindow window;
79 private Set<WindowListener> listeners
80 = Collections.synchronizedSet(new HashSet<WindowListener>());
82 /**
83 * @param listener Callback on window close
85 public void addListener(final WindowListener listener) {
86 listeners.add(listener);
89 /**
90 * @param listener Callback on window close
92 public void removeListener(final WindowListener listener) {
93 listeners.remove(listener);
96 public void setWindow(final NSWindow window) {
97 this.window = window;
98 window.setReleasedWhenClosed(!this.isSingleton());
99 window.setDelegate(this.id());
102 public NSWindow window() {
103 return window;
107 * A singleton window is not released when closed and the controller is not invalidated
109 * @return Always false
110 * @see #invalidate()
111 * @see ch.cyberduck.binding.application.NSWindow#setReleasedWhenClosed(boolean)
113 public boolean isSingleton() {
114 return false;
118 * @return True if the controller window is on screen.
120 public boolean isVisible() {
121 final NSWindow w = this.window();
122 if(null == w) {
123 return false;
125 return w.isVisible();
128 @Override
129 public void windowDidBecomeKey(final NSNotification notification) {
133 @Override
134 public void windowDidResignKey(final NSNotification notification) {
138 @Override
139 public void windowDidBecomeMain(final NSNotification notification) {
143 @Override
144 public void windowDidResignMain(final NSNotification notification) {
148 public void windowWillEnterFullScreen(final NSNotification notification) {
152 public void windowWillExitFullScreen(final NSNotification notification) {
156 public void windowDidFailToEnterFullScreen(final NSWindow window) {
157 log.error("Error entering full screen");
161 * @see ch.cyberduck.binding.application.NSWindow.Delegate
163 @Override
164 public boolean windowShouldClose(final NSWindow sender) {
165 return true;
169 * Override this method if the controller should not be invalidated after its window closes
171 @Override
172 public void windowWillClose(final NSNotification notification) {
173 if(log.isDebugEnabled()) {
174 log.debug(String.format("Window will close %s", notification));
176 for(WindowListener listener : listeners.toArray(new WindowListener[listeners.size()])) {
177 listener.windowWillClose();
179 if(!this.isSingleton()) {
180 //If the window is closed it is assumed the controller object is no longer used
181 this.invalidate();
186 * Position this controller's window relative to other open windows
188 protected NSPoint cascade(final NSPoint point) {
189 return window.cascadeTopLeftFromPoint(point);
193 * @param toggle Checkbox
194 * @param select Selected
196 protected void setState(final NSButton toggle, final boolean select) {
197 if(select) {
198 toggle.performClick(null);
200 toggle.setState(select ? NSCell.NSOnState : NSCell.NSOffState);
204 * @return True if this window has a sheet attached
206 public boolean hasSheet() {
207 if(null == window) {
208 return false;
210 return window.attachedSheet() != null;
213 @Override
214 public boolean alert(final Host host, final BackgroundException failure,
215 final StringBuilder transcript) {
216 return new PanelAlertCallback(this).alert(host, failure, transcript);
220 * @param alert Sheet
221 * @return Return code from the dialog if called from background thread.
223 @Override
224 protected int alert(final NSAlert alert) {
225 return this.alert(alert, (String) null);
229 * @param alert Sheet
230 * @param help Help URL
231 * @return Button selection
233 protected int alert(final NSAlert alert, final String help) {
234 final int[] response = new int[1];
235 this.alert(alert, new SheetCallback() {
236 @Override
237 public void callback(final int returncode) {
238 response[0] = returncode;
240 }, help);
241 return response[0];
245 * Display alert as sheet to the window of this controller
247 * @param alert Sheet
248 * @param callback Dismissed notification
250 protected void alert(final NSAlert alert, final SheetCallback callback) {
251 this.alert(alert, callback, null);
255 * @param alert Sheet
256 * @param callback Dismissed notification
257 * @param help Help URL
259 protected void alert(final NSAlert alert, final SheetCallback callback, final String help) {
260 final SheetController c = new AlertController(this, alert) {
261 @Override
262 public void callback(final int returncode) {
263 callback.callback(returncode);
266 @Override
267 protected void help() {
268 if(StringUtils.isBlank(help)) {
269 super.help();
271 else {
272 BrowserLauncherFactory.get().open(help);
276 c.beginSheet();
280 * Attach a sheet to this window
282 * @param sheet The sheet to be attached to this window
283 * @see SheetController#beginSheet()
285 protected void alert(final NSWindow sheet) {
286 this.alert(sheet, new SheetCallback() {
287 @Override
288 public void callback(final int returncode) {
295 * Attach a sheet to this window
297 * @param sheet The sheet to be attached to this window
298 * @param callback The callback to call after the sheet is dismissed
299 * @see SheetController#beginSheet()
301 protected void alert(final NSWindow sheet, final SheetCallback callback) {
302 final SheetController c = new SheetController(this) {
303 @Override
304 public void callback(final int returncode) {
305 callback.callback(returncode);
308 @Override
309 public NSWindow window() {
310 return sheet;
313 c.beginSheet();
316 protected void updateField(final NSTextView f, final String value) {
317 f.setString(StringUtils.isNotBlank(value) ? value : StringUtils.EMPTY);
320 protected void updateField(final NSTextField f, final String value) {
321 f.setStringValue(StringUtils.isNotBlank(value) ? value : StringUtils.EMPTY);
324 protected void updateField(final NSTextField f, final String value, final NSDictionary attributes) {
325 f.setAttributedStringValue(NSAttributedString.attributedStringWithAttributes(StringUtils.isNotBlank(value) ? value : StringUtils.EMPTY, attributes));
329 @Action
330 public void helpButtonClicked(final NSButton sender) {
331 BrowserLauncherFactory.get().open(PreferencesFactory.get().getProperty("website.help"));
334 protected void print(NSView view) {
335 NSPrintInfo print = NSPrintInfo.sharedPrintInfo();
336 print.setOrientation(NSPrintInfo.NSPrintingOrientation.NSLandscapeOrientation);
337 NSPrintOperation op = NSPrintOperation.printOperationWithView_printInfo(view, print);
338 op.setShowsPrintPanel(true);
339 final NSPrintPanel panel = op.printPanel();
340 panel.setOptions(panel.options() | NSPrintPanel.NSPrintPanelShowsOrientation
341 | NSPrintPanel.NSPrintPanelShowsPaperSize | NSPrintPanel.NSPrintPanelShowsScaling);
342 op.runOperationModalForWindow_delegate_didRunSelector_contextInfo(this.window(), this.id(),
343 Foundation.selector("printOperationDidRun:success:contextInfo:"), null);
346 public void printOperationDidRun_success_contextInfo(NSPrintOperation op, boolean success, ID contextInfo) {
347 if(!success) {
348 log.warn(String.format("Printing failed for context %s", contextInfo));