Merge pull request #2688 from huangruichang/master

* add desktop-environment-integration.md and and online-offline-event…
This commit is contained in:
Cheng Zhao 2015-09-03 17:12:46 +09:00
commit f6d6a2a4c3
2 changed files with 239 additions and 0 deletions

View file

@ -0,0 +1,167 @@
# 桌面环境集成
不同的操作系统在各自的桌面应用上提供了不同的特性。例如,在 windows 上应用曾经打开的文件会出现在任务栏的跳转列表,在 Mac 上,应用可以把自定义菜单放在鱼眼菜单上。
本章将会说明怎样使用 Electron APIs 把你的应用和桌面环境集成到一块。
## 最近文档 (Windows & OS X)
Windows 和 OS X 提供获取最近文档列表的便捷方式,那就是打开跳转列表或者鱼眼菜单。
跳转列表:
![JumpList][1]
鱼眼菜单:
![Dock Menu][2]
为了增加一个文件到最近文件列表,你可以使用 [app.addRecentDocument][3] API:
````
var app = require('app');
app.addRecentDocument('/Users/USERNAME/Desktop/work.type');
````
或者你也可以使用 [app.clearRecentDocuments][4] API 来清空最近文件列表。
````
app.clearRecentDocuments();
````
## Windows 需注意
为了这个特性在 Windows 上表现正常,你的应用需要被注册成为一种文件类型的句柄,否则,在你注册之前,文件不会出现在跳转列表。你可以在 [Application Registration][5] 里找到任何关于注册事宜的说明。
## OS X 需注意
当一个文件被最近文件列表请求时,`app` 模块里的 `open-file` 事件将会被发出。
## 自定义的鱼眼菜单(OS X)
OS X 可以让开发者定制自己的菜单,通常会包含一些常用特性的快捷方式。
### 菜单中的终端
[Dock menu of Terminal.app][6]
使用 `app.dock.setMenu` API 来设置你的菜单,这仅在 OS X 上可行:
````
var app = require('app');
var Menu = require('menu');
var dockMenu = Menu.buildFromTemplate([
{ label: 'New Window', click: function() { console.log('New Window'); } },
{ label: 'New Window with Settings', submenu: [
{ label: 'Basic' },
{ label: 'Pro'}
]},
{ label: 'New Command...'}
]);
app.dock.setMenu(dockMenu);
````
## 用户任务(Windows)
在 Windows你可以特别定义跳转列表的 `Tasks` 目录的行为,引用 MSDN 的文档:
> Applications define tasks based on both the program's features and the key things a user is expected to do with them. Tasks should be context-free, in that the application does not need to be running for them to work. They should also be the statistically most common actions that a normal user would perform in an application, such as compose an email message or open the calendar in a mail program, create a new document in a word processor, launch an application in a certain mode, or launch one of its subcommands. An application should not clutter the menu with advanced features that standard users won't need or one-time actions such as registration. Do not use tasks for promotional items such as upgrades or special offers.
> It is strongly recommended that the task list be static. It should remain the same regardless of the state or status of the application. While it is possible to vary the list dynamically, you should consider that this could confuse the user who does not expect that portion of the destination list to change.
### IE 的任务
![IE][7]
不同于 OS X 的鱼眼菜单Windows 上的用户任务表现得更像一个快捷方式,比如当用户点击一个任务,一个程序将会被传入特定的参数并且运行。
你可以使用 [app.setUserTasks][8] API 来设置你的应用中的用户任务:
````
var app = require('app');
app.setUserTasks([
{
program: process.execPath,
arguments: '--new-window',
iconPath: process.execPath,
iconIndex: 0,
title: 'New Window',
description: 'Create a new window'
}
]);
````
调用 `app.setUserTasks` 并传入空数组就可以清除你的任务列表:
````
app.setUserTasks([]);
````
当你的应用关闭时,用户任务会仍然会出现,在你的应用被卸载前,任务指定的图标和程序的路径必须是存在的。
### 缩略图工具栏
在 Windows你可以在任务栏上添加一个按钮来当作应用的缩略图工具栏。它将提供用户一种用户访问常用窗口的方式并且不需要恢复或者激活窗口。
在 MSDN它被如是说
> This toolbar is simply the familiar standard toolbar common control. It has a maximum of seven buttons. Each button's ID, image, tooltip, and state are defined in a structure, which is then passed to the taskbar. The application can show, enable, disable, or hide buttons from the thumbnail toolbar as required by its current state.
> For example, Windows Media Player might offer standard media transport controls such as play, pause, mute, and stop.
### Windows Media Player 的缩略图工具栏
![Thumbnail toolbar of Windows Media Player][9]
你可以使用 [BrowserWindow.setThumbarButtons][10] 来设置你的应用的缩略图工具栏。
````
var BrowserWindow = require('browser-window');
var path = require('path');
var win = new BrowserWindow({
width: 800,
height: 600
});
win.setThumbarButtons([
{
tooltip: "button1",
icon: path.join(__dirname, 'button1.png'),
click: function() { console.log("button2 clicked"); }
},
{
tooltip: "button2",
icon: path.join(__dirname, 'button2.png'),
flags:['enabled', 'dismissonclick'],
click: function() { console.log("button2 clicked."); }
}
]);
````
调用 `BrowserWindow.setThumbarButtons` 并传入空数组即可清空缩略图工具栏:
````
win.setThumbarButtons([]);
````
## Unity launcher 快捷方式(Linux)
在 Unity,你可以通过改变 `.desktop` 文件来增加自定义运行器的快捷方式,详情看 [Adding shortcuts to a launcher][11]。
### Audacious 运行器的快捷方式:
![Launcher shortcuts of Audacious][12]
## 任务栏的进度条(Windows & Unity)
在 Windows进度条可以出现在一个任务栏按钮之上。这可以提供进度信息给用户而不需要用户切换应用窗口。
Unity DE 也具有同样的特性,在运行器上显示进度条。
### 在任务栏上的进度条:
![Progress bar in taskbar button][13]
### 在 Unity 运行器上的进度条
![Progress bar in Unity launcher][14]
给一个窗口设置进度条,你可以调用 [BrowserWindow.setProgressBar][15] API
````
var window = new BrowserWindow({...});
window.setProgressBar(0.5);
````
在 OS X一个窗口可以设置它展示的文件文件的图标可以出现在标题栏当用户 Command-Click 或者 Control-Click 标题栏,文件路径弹窗将会出现。
### 展示文件弹窗菜单:
![Represented file popup menu][16]
你可以调用 [BrowserWindow.setRepresentedFilename][17] 和 [BrowserWindow.setDocumentEdited][18] APIs
````
var window = new BrowserWindow({...});
window.setRepresentedFilename('/etc/passwd');
window.setDocumentEdited(true);
````
[1]:https://camo.githubusercontent.com/3310597e01f138b1d687e07aa618c50908a88dec/687474703a2f2f692e6d73646e2e6d6963726f736f66742e636f6d2f64796e696d672f49433432303533382e706e67
[2]: https://cloud.githubusercontent.com/assets/639601/5069610/2aa80758-6e97-11e4-8cfb-c1a414a10774.png
[3]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/app.md
[4]: https://github.com/atom/electron/blob/master/docs/tutorial/clearrecentdocuments
[5]: https://msdn.microsoft.com/en-us/library/windows/desktop/ee872121%28v=vs.85%29.aspx
[6]: https://cloud.githubusercontent.com/assets/639601/5069962/6032658a-6e9c-11e4-9953-aa84006bdfff.png
[7]: https://camo.githubusercontent.com/30154e0cc36acfc968ac9ae076a8f0d6600dd736/687474703a2f2f692e6d73646e2e6d6963726f736f66742e636f6d2f64796e696d672f49433432303533392e706e67
[8]: https://github.com/atom/electron/blob/master/docs/api/app.md#appsetusertaskstasks
[9]: https://camo.githubusercontent.com/098cb0f52f27084a80ec6429e51a195df3d8c333/68747470733a2f2f692d6d73646e2e7365632e732d6d7366742e636f6d2f64796e696d672f49433432303534302e706e67
[10]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/browser-window.md
[11]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
[12]: https://camo.githubusercontent.com/b6f54e2bc3206ebf8e08dd029529af9ec84d58ae/68747470733a2f2f68656c702e7562756e74752e636f6d2f636f6d6d756e6974792f556e6974794c61756e6368657273416e644465736b746f7046696c65733f616374696f6e3d41747461636846696c6526646f3d676574267461726765743d73686f7274637574732e706e67
[13]: https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png
[14]: https://cloud.githubusercontent.com/assets/639601/5081747/4a0a589e-6f0f-11e4-803f-91594716a546.png
[15]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/browser-window.md
[16]: https://cloud.githubusercontent.com/assets/639601/5082061/670a949a-6f14-11e4-987a-9aaa04b23c1d.png
[17]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/browser-window.md
[18]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/browser-window.md

View file

@ -0,0 +1,72 @@
# 在线/离线事件探测
使用标准 HTML5 APIs 可以实现在线和离线事件的探测,就像以下例子:
*main.js*
````
var app = require('app');
var BrowserWindow = require('browser-window');
var onlineStatusWindow;
app.on('ready', function() {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false });
onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html');
});
````
*online-status.html*
````
<!DOCTYPE html>
<html>
<body>
<script>
var alertOnlineStatus = function() {
window.alert(navigator.onLine ? 'online' : 'offline');
};
window.addEventListener('online', alertOnlineStatus);
window.addEventListener('offline', alertOnlineStatus);
alertOnlineStatus();
</script>
</body>
</html>
````
也会有人想要在主进程也有回应这些事件的实例。然后主进程没有 `navigator` 对象因此不能直接探测在线还是离线。使用 Electron 的进程间通讯工具,事件就可以在主进程被使,就像下面的例子:
*main.js*
````
var app = require('app');
var ipc = require('ipc');
var BrowserWindow = require('browser-window');
var onlineStatusWindow;
app.on('ready', function() {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false });
onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html');
});
ipc.on('online-status-changed', function(event, status) {
console.log(status);
});
````
*online-status.html*
````
<!DOCTYPE html>
<html>
<body>
<script>
var ipc = require('ipc');
var updateOnlineStatus = function() {
ipc.send('online-status-changed', navigator.onLine ? 'online' : 'offline');
};
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOnlineStatus);
updateOnlineStatus();
</script>
</body>
</html>
````