From 7dc9a9bf2ffc5b1cad4dfe1f19c83e9ddadfd499 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Mon, 15 Jul 2013 13:51:42 -0400 Subject: [PATCH] bluetooth: Adapt to new designs for the bluetooth menu This is a part of the new system status design, see https://wiki.gnome.org/GnomeShell/Design/Guidelines/SystemStatus/ for design details. https://bugzilla.gnome.org/show_bug.cgi?id=704368 --- js/ui/status/bluetooth.js | 255 ++++---------------------------------- 1 file changed, 21 insertions(+), 234 deletions(-) diff --git a/js/ui/status/bluetooth.js b/js/ui/status/bluetooth.js index aa7505c0f..f2db97625 100644 --- a/js/ui/status/bluetooth.js +++ b/js/ui/status/bluetooth.js @@ -13,13 +13,6 @@ const NotificationDaemon = imports.ui.notificationDaemon; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -const ConnectionState = { - DISCONNECTED: 0, - CONNECTED: 1, - DISCONNECTING: 2, - CONNECTING: 3 -} - const Indicator = new Lang.Class({ Name: 'BTIndicator', Extends: PanelMenu.SystemStatusButton, @@ -27,59 +20,18 @@ const Indicator = new Lang.Class({ _init: function() { this.parent('bluetooth-disabled-symbolic', _("Bluetooth")); + // The Bluetooth menu only appears when Bluetooth is in use, + // so just statically build it with a "Turn Off" menu item. + this._item = new PopupMenu.PopupSubMenuMenuItem(_("Bluetooth"), true); + this._item.icon.icon_name = 'bluetooth-active-symbolic'; + this._item.menu.addAction(_("Turn Off"), Lang.bind(this, function() { + this._applet.killswitch_state = GnomeBluetooth.KillswitchState.SOFT_BLOCKED; + })); + this._item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop'); + this._applet = new GnomeBluetoothApplet.Applet(); - - this._killswitch = new PopupMenu.PopupSwitchMenuItem(_("Bluetooth"), false); - this._applet.connect('notify::killswitch-state', Lang.bind(this, this._updateKillswitch)); - this._killswitch.connect('toggled', Lang.bind(this, function() { - let current_state = this._applet.killswitch_state; - if (current_state != GnomeBluetooth.KillswitchState.HARD_BLOCKED && - current_state != GnomeBluetooth.KillswitchState.NO_ADAPTER) { - this._applet.killswitch_state = this._killswitch.state ? - GnomeBluetooth.KillswitchState.UNBLOCKED: - GnomeBluetooth.KillswitchState.SOFT_BLOCKED; - } else - this._killswitch.setToggleState(false); - })); - - this._discoverable = new PopupMenu.PopupSwitchMenuItem(_("Visibility"), this._applet.discoverable); - this._applet.connect('notify::discoverable', Lang.bind(this, function() { - this._discoverable.setToggleState(this._applet.discoverable); - })); - this._discoverable.connect('toggled', Lang.bind(this, function() { - this._applet.discoverable = this._discoverable.state; - })); - - this._updateKillswitch(); - this.menu.addMenuItem(this._killswitch); - this.menu.addMenuItem(this._discoverable); - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - - this._fullMenuItems = [new PopupMenu.PopupSeparatorMenuItem(), - new PopupMenu.PopupMenuItem(_("Send Files to Device…")), - new PopupMenu.PopupMenuItem(_("Set Up a New Device…")), - new PopupMenu.PopupSeparatorMenuItem()]; - this._hasDevices = false; - - this._fullMenuItems[1].connect('activate', function() { - GLib.spawn_command_line_async('bluetooth-sendto'); - }); - this._fullMenuItems[2].connect('activate', function() { - GLib.spawn_command_line_async('bluetooth-wizard'); - }); - - for (let i = 0; i < this._fullMenuItems.length; i++) { - let item = this._fullMenuItems[i]; - this.menu.addMenuItem(item); - } - - this._deviceItemPosition = 3; - this._deviceItems = []; - this._applet.connect('devices-changed', Lang.bind(this, this._updateDevices)); - this._updateDevices(); - - this._applet.connect('notify::show-full-menu', Lang.bind(this, this._updateFullMenu)); - this._updateFullMenu(); + this._applet.connect('devices-changed', Lang.bind(this, this._sync)); + this._sync(); this._applet.connect('pincode-request', Lang.bind(this, this._pinRequest)); this._applet.connect('confirm-request', Lang.bind(this, this._confirmRequest)); @@ -88,183 +40,18 @@ const Indicator = new Lang.Class({ this._applet.connect('cancel-request', Lang.bind(this, this._cancelRequest)); }, - _updateKillswitch: function() { - let current_state = this._applet.killswitch_state; - let on = current_state == GnomeBluetooth.KillswitchState.UNBLOCKED; - let has_adapter = current_state != GnomeBluetooth.KillswitchState.NO_ADAPTER; - let can_toggle = current_state != GnomeBluetooth.KillswitchState.NO_ADAPTER && - current_state != GnomeBluetooth.KillswitchState.HARD_BLOCKED; + _sync: function() { + let connectedDevices = this._applet.get_devices().filter(function(device) { + return device.connected; + }); + let nDevices = connectedDevices.length; - this._killswitch.setToggleState(on); - if (can_toggle) - this._killswitch.setStatus(null); - else - /* TRANSLATORS: this means that bluetooth was disabled by hardware rfkill */ - this._killswitch.setStatus(_("hardware disabled")); + let on = nDevices > 0; + this.mainIcon.visible = on; + this.actor.visible = on; - this.actor.visible = has_adapter; - - if (on) { - this._discoverable.actor.show(); - this.setIcon('bluetooth-active-symbolic'); - } else { - this._discoverable.actor.hide(); - this.setIcon('bluetooth-disabled-symbolic'); - } - }, - - _updateDevices: function() { - let devices = this._applet.get_devices(); - - let newlist = [ ]; - for (let i = 0; i < this._deviceItems.length; i++) { - let item = this._deviceItems[i]; - let destroy = true; - for (let j = 0; j < devices.length; j++) { - if (item._device.device_path == devices[j].device_path) { - this._updateDeviceItem(item, devices[j]); - destroy = false; - break; - } - } - if (destroy) - item.destroy(); - else - newlist.push(item); - } - - this._deviceItems = newlist; - this._hasDevices = newlist.length > 0; - for (let i = 0; i < devices.length; i++) { - let d = devices[i]; - if (d._item) - continue; - let item = this._createDeviceItem(d); - if (item) { - this.menu.addMenuItem(item, this._deviceItemPosition + this._deviceItems.length); - this._deviceItems.push(item); - this._hasDevices = true; - } - } - }, - - _updateDeviceItem: function(item, device) { - if (!device.can_connect && device.capabilities == GnomeBluetoothApplet.Capabilities.NONE) { - item.destroy(); - return; - } - - let prevDevice = item._device; - let prevCapabilities = prevDevice.capabilities; - let prevCanConnect = prevDevice.can_connect; - - // adopt the new device object - item._device = device; - device._item = item; - - // update properties - item.label.text = device.alias; - - if (prevCapabilities != device.capabilities || - prevCanConnect != device.can_connect) { - // need to rebuild the submenu - item.menu.removeAll(); - this._buildDeviceSubMenu(item, device); - } - - // update connected property - if (device.can_connect) - item._connectedMenuItem.setToggleState(device.connected); - }, - - _createDeviceItem: function(device) { - if (!device.can_connect && device.capabilities == GnomeBluetoothApplet.Capabilities.NONE) - return null; - let item = new PopupMenu.PopupSubMenuMenuItem(device.alias); - - // adopt the device object, and add a back link - item._device = device; - device._item = item; - - this._buildDeviceSubMenu(item, device); - - return item; - }, - - _buildDeviceSubMenu: function(item, device) { - if (device.can_connect) { - let menuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected); - item._connected = device.connected; - item._connectedMenuItem = menuitem; - menuitem.connect('toggled', Lang.bind(this, function() { - if (item._connected > ConnectionState.CONNECTED) { - // operation already in progress, revert - // (should not happen anyway) - menuitem.setToggleState(menuitem.state); - } - if (item._connected) { - item._connected = ConnectionState.DISCONNECTING; - menuitem.setStatus(_("disconnecting...")); - this._applet.disconnect_device(item._device.device_path, function(applet, success) { - if (success) { // apply - item._connected = ConnectionState.DISCONNECTED; - menuitem.setToggleState(false); - } else { // revert - item._connected = ConnectionState.CONNECTED; - menuitem.setToggleState(true); - } - menuitem.setStatus(null); - }); - } else { - item._connected = ConnectionState.CONNECTING; - menuitem.setStatus(_("connecting...")); - this._applet.connect_device(item._device.device_path, function(applet, success) { - if (success) { // apply - item._connected = ConnectionState.CONNECTED; - menuitem.setToggleState(true); - } else { // revert - item._connected = ConnectionState.DISCONNECTED; - menuitem.setToggleState(false); - } - menuitem.setStatus(null); - }); - } - })); - - item.menu.addMenuItem(menuitem); - } - - if (device.capabilities & GnomeBluetoothApplet.Capabilities.OBEX_PUSH) { - item.menu.addAction(_("Send Files…"), Lang.bind(this, function() { - this._applet.send_to_address(device.bdaddr, device.alias); - })); - } - }, - - _updateFullMenu: function() { - if (this._applet.show_full_menu) { - this._showAll(this._fullMenuItems); - if (this._hasDevices) - this._showAll(this._deviceItems); - } else { - this._hideAll(this._fullMenuItems); - this._hideAll(this._deviceItems); - } - }, - - _showAll: function(items) { - for (let i = 0; i < items.length; i++) - items[i].actor.show(); - }, - - _hideAll: function(items) { - for (let i = 0; i < items.length; i++) - items[i].actor.hide(); - }, - - _destroyAll: function(items) { - for (let i = 0; i < items.length; i++) - items[i].destroy(); + if (on) + this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices").format(nDevices); }, _ensureSource: function() {