├── README.markdown ├── build.properties ├── build.xml ├── droidex ├── lib └── args4j-2.0.16.jar └── src └── com └── commonsware └── droidex ├── Actions.java ├── DroidEx.java ├── StartupOptions.java ├── action ├── ExitAction.java ├── OpenDeviceAction.java ├── OpenRecordingAction.java └── SettingsAction.java ├── image ├── AbstractImageFilter.java ├── DeviceScreenImageProvider.java ├── IImageFilter.java ├── IImageProvider.java ├── Orientation.java ├── RecordImageFilter.java ├── RenderSettings.java ├── RotateImageFilter.java └── ScaleImageFilter.java └── ui ├── DeviceScreenView.java ├── DroidExMenuBar.java └── DroidExToolBar.java /README.markdown: -------------------------------------------------------------------------------- 1 | DroidEx: Projecting Android on the Big(ger) Screen 2 | ================================================== 3 | 4 | DroidEx displays a copy of your attached Android device's screen on 5 | your own development machine's screen. Mostly, this is useful for 6 | presentations, as you can attach an Android device to a notebook attached 7 | to a projector, and your audience can see what is on the device. In 8 | particular, this is good for demonstrations of things that cannot 9 | readily be demonstrated via the emulator, such as GPS access or the 10 | accelerometer. 11 | 12 | This version of DroidEx works with the Android 2.0 SDK. 13 | 14 | Usage 15 | ----- 16 | This version of `droidex` takes 0-1 command-line parameters. The one 17 | possible parameter is a floating-point value representing by how much 18 | to scale the image (e.g., a scale of 1.25 on an HVGA device will give you 19 | a 600x400 projected image). By default, the scale is 1.0, meaning the 20 | project image will be as many pixels as is the physical screen size. 21 | 22 | ### Linux & OS X 23 | 24 | Set your ANDROID_HOME environment variable to point to the base directory 25 | where your Android SDK is installed. Then, just run the `droidex` shell 26 | script. 27 | 28 | ### Windows 29 | 30 | It is probably easiest to just copy the `droidex` shell script to a 31 | `droidex.cmd` batch file, change the classpath separator, replace `$ANDROID_HOME` 32 | with the proper value for your PC, and use the batch file. Also, you will 33 | need to replace `$1` with `%1`. 34 | 35 | Dependencies 36 | ------------ 37 | The Android 2.0 SDK, or at least ddmlib.jar. 38 | 39 | Compatibility 40 | ------------- 41 | DroidEx is known to work with: 42 | 1. T-Mobile G1 43 | 2. Google Ion 44 | 3. HTC Tattoo 45 | 4. Motorola DROID 46 | 47 | DroidEx is known not to work with: 48 | 1. HTC Hero (at least early versions distributed by Sprint in the US) 49 | 2. ARCHOS 5 Android tablet 50 | 51 | Version 52 | ------- 53 | This is version 1.0, meaning DroidEx has been used a fair bit. 54 | 55 | License 56 | ------- 57 | The code in this project is licensed under the Apache 58 | Software License 2.0, per the terms of the included LICENSE 59 | file. 60 | 61 | Open Source Development 62 | ----------------------- 63 | Those interested in contributing to DroidEx may be interested 64 | in the project's [Lighthouse issue tracker][lh] and the project's 65 | [development Google Group][dgg]. 66 | 67 | Questions 68 | --------- 69 | If you have questions regarding the use of this code, please 70 | join and ask them on the [cw-android Google Group][gg]. Be sure to 71 | indicate which application you have questions about. 72 | 73 | [gg]: http://groups.google.com/group/cw-android 74 | [dgg]: http://groups.google.com/group/droidex 75 | [lh]: https://commonsware.lighthouseapp.com/projects/41963-droidex 76 | -------------------------------------------------------------------------------- /build.properties: -------------------------------------------------------------------------------- 1 | sdk-folder="/opt/android-sdk-linux_x86-1.6_r1" 2 | android-tools="/opt/android-sdk-linux_x86-1.6_r1/tools" 3 | android-jar="${sdk-folder}/android.jar" 4 | android-framework="${android-tools}/lib/framework.aidl" 5 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | Packaging java... 58 | 61 | 62 | 63 | 64 | 73 | 74 | 75 | 76 | 77 | Copyright © 2009 CommonsWare, LLC. All Rights Reserved.]]> 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /droidex: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | java -cp bin/DroidEx.jar:$ANDROID_HOME/tools/lib/ddmlib.jar com.commonsware.droidex.DroidEx $1 -------------------------------------------------------------------------------- /lib/args4j-2.0.16.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subfuzion/droidex/0198ca348132a5a0131f75fc9fc4c166d670e424/lib/args4j-2.0.16.jar -------------------------------------------------------------------------------- /src/com/commonsware/droidex/Actions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex; 19 | 20 | import com.commonsware.droidex.action.*; 21 | 22 | import javax.swing.*; 23 | import java.awt.event.InputEvent; 24 | import java.awt.event.KeyEvent; 25 | 26 | public final class Actions { 27 | public static Action OpenDeviceAction; 28 | public static Action OpenRecordingAction; 29 | public static Action SettingsAction; 30 | public static Action ExitAction; 31 | 32 | static 33 | { 34 | OpenDeviceAction = new OpenDeviceAction("Open Device..."); 35 | OpenDeviceAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_O); 36 | OpenDeviceAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)); 37 | 38 | OpenRecordingAction = new OpenRecordingAction("Open Recording..."); 39 | OpenRecordingAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_R); 40 | OpenRecordingAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK)); 41 | 42 | SettingsAction = new SettingsAction("Settings..."); 43 | SettingsAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S); 44 | SettingsAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); 45 | 46 | ExitAction = new ExitAction("Exit"); 47 | ExitAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_X); 48 | ExitAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_DOWN_MASK)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/DroidEx.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex; 19 | 20 | import com.android.ddmlib.AndroidDebugBridge; 21 | import com.android.ddmlib.IDevice; 22 | import com.commonsware.droidex.image.*; 23 | import com.commonsware.droidex.ui.DeviceScreenView; 24 | import com.commonsware.droidex.ui.DroidExMenuBar; 25 | import com.commonsware.droidex.ui.DroidExToolBar; 26 | import org.kohsuke.args4j.CmdLineException; 27 | import org.kohsuke.args4j.CmdLineParser; 28 | 29 | import javax.swing.*; 30 | import java.awt.*; 31 | import java.beans.PropertyChangeEvent; 32 | import java.beans.PropertyChangeListener; 33 | import java.io.IOException; 34 | 35 | /** 36 | * Displays a copy of the device's screen. 37 | */ 38 | public class DroidEx extends JFrame { 39 | private IDevice device = null; 40 | private StartupOptions options; 41 | private RenderSettings settings; 42 | private DeviceScreenView deviceScreenView; 43 | 44 | public DroidEx(StartupOptions options) throws IOException { 45 | this.options = options; 46 | 47 | AndroidDebugBridge bridge = AndroidDebugBridge.createBridge(); 48 | sleep(1000); // allow sync 49 | 50 | try { 51 | initDevice(bridge); 52 | initRenderSettings(); 53 | initDeviceScreenView(); 54 | initFrame(deviceScreenView); 55 | } 56 | finally { 57 | AndroidDebugBridge.disconnectBridge(); 58 | } 59 | } 60 | 61 | private void initDevice(AndroidDebugBridge bridge) { 62 | IDevice[] devices = bridge.getDevices(); 63 | device = devices[0]; 64 | } 65 | 66 | private void initRenderSettings() { 67 | settings = new RenderSettings(); 68 | settings.setScale(options.scale); 69 | settings.setOrientation(options.orientation); 70 | } 71 | 72 | private void initDeviceScreenView() { 73 | IImageProvider imageProvider = new DeviceScreenImageProvider(device); 74 | imageProvider.addImageFilter(new ScaleImageFilter(settings)); 75 | imageProvider.addImageFilter(new RotateImageFilter(settings)); 76 | imageProvider.addImageFilter(new RecordImageFilter(settings)); 77 | 78 | deviceScreenView = new DeviceScreenView(imageProvider); 79 | deviceScreenView.setFrameRate(options.frameRate); 80 | deviceScreenView.play(); 81 | 82 | settings.addPropertyChangeListener(new PropertyChangeListener() { 83 | public void propertyChange(PropertyChangeEvent event) { 84 | deviceScreenView.repaint(); 85 | } 86 | }); 87 | } 88 | 89 | private void initFrame(JPanel panel) { 90 | initLookAndFeel(); 91 | this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 92 | this.setJMenuBar(new DroidExMenuBar()); 93 | initChildComponents(panel); 94 | this.pack(); 95 | centerFrame(this); 96 | } 97 | 98 | private void initLookAndFeel() 99 | { 100 | try { 101 | try { 102 | JFrame.setDefaultLookAndFeelDecorated(true); 103 | for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { 104 | if ("Nimbus".equals(info.getName())) { 105 | UIManager.setLookAndFeel(info.getClassName()); 106 | break; 107 | } 108 | } 109 | } catch (Exception e) { 110 | UIManager.setLookAndFeel( 111 | UIManager.getSystemLookAndFeelClassName()); 112 | } 113 | } catch (Exception e) { 114 | JFrame.setDefaultLookAndFeelDecorated(false); 115 | } 116 | } 117 | 118 | private void initChildComponents(JPanel panel) { 119 | setLayout(new BorderLayout()); 120 | add(new DroidExToolBar(), BorderLayout.NORTH); 121 | JScrollPane scrollPane = new JScrollPane(panel); 122 | scrollPane.setSize(panel.getPreferredSize()); 123 | this.add(new JScrollPane(panel)); 124 | } 125 | 126 | private static void centerFrame(Component component) { 127 | Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 128 | component.setLocation( 129 | (screenSize.width - component.getWidth()) / 2, 130 | (screenSize.height - component.getHeight()) / 2); 131 | } 132 | 133 | private static void sleep(long millis) { 134 | try { 135 | Thread.sleep(millis); 136 | } catch (Throwable t) { 137 | } 138 | } 139 | 140 | public static void main(String[] args) throws IOException { 141 | StartupOptions options = new StartupOptions(); 142 | CmdLineParser parser = new CmdLineParser(options); 143 | 144 | try { 145 | // options contain the parsed args 146 | parser.parseArgument(args); 147 | DroidEx droidex = new DroidEx(options); 148 | droidex.setVisible(true); 149 | 150 | } catch (CmdLineException e) { 151 | System.err.println(e.getMessage()); 152 | System.err.println("droidex [options...]"); 153 | parser.printUsage(System.err); 154 | return; 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/StartupOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex; 19 | 20 | import com.commonsware.droidex.image.Orientation; 21 | import org.kohsuke.args4j.Argument; 22 | import org.kohsuke.args4j.Option; 23 | 24 | import java.io.File; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | /** 29 | * Startup options parsed from command line arguments. 30 | */ 31 | public class StartupOptions { 32 | /** 33 | * The device/emulator to connect to. 34 | */ 35 | @Option(name = "-d", aliases = "--device", usage = "the device or emulator to connect to") 36 | public String device; 37 | 38 | /** 39 | * The scaling factor. 40 | */ 41 | @Option(name = "-s", aliases = "--scale", usage = "the amount to scale the image by") 42 | public Double scale = 1.5d; 43 | 44 | /** 45 | * The initial rotation, should be "portrait" or "landscape". 46 | */ 47 | @Option(name = "-o", aliases = "--orientation", usage = "portrait | landscape") 48 | public Orientation orientation; 49 | 50 | @Option(name = "-f", aliases = "--framerate", usage = "the screen refresh rate (frames per second)") 51 | public int frameRate = 10; 52 | 53 | /** 54 | * The directory to record images to. 55 | */ 56 | @Option(name = "-r", aliases = "--record", usage = "the directory to record images to (recording begins immediately)") 57 | public File record; 58 | 59 | /** 60 | * For other command line arguments aside from options 61 | */ 62 | @Argument 63 | private List arguments = new ArrayList(); 64 | } 65 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/action/ExitAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.action; 19 | 20 | import javax.swing.*; 21 | import java.awt.event.ActionEvent; 22 | 23 | public class ExitAction extends AbstractAction { 24 | /** 25 | * Defines an Action object with a default 26 | * description string and default icon. 27 | */ 28 | public ExitAction() { 29 | } 30 | 31 | /** 32 | * Defines an Action object with the specified 33 | * description string and a default icon. 34 | */ 35 | public ExitAction(String name) { 36 | super(name); 37 | } 38 | 39 | /** 40 | * Defines an Action object with the specified 41 | * description string and a the specified icon. 42 | */ 43 | public ExitAction(String name, Icon icon) { 44 | super(name, icon); 45 | } 46 | 47 | /** 48 | * Invoked when an action occurs. 49 | */ 50 | public void actionPerformed(ActionEvent e) { 51 | // TODO: will want a graceful exit if DroidEx is recording 52 | System.exit(0); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/action/OpenDeviceAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.action; 19 | 20 | import javax.swing.*; 21 | import java.awt.event.ActionEvent; 22 | 23 | public class OpenDeviceAction extends AbstractAction { 24 | /** 25 | * Defines an Action object with a default 26 | * description string and default icon. 27 | */ 28 | public OpenDeviceAction() { 29 | } 30 | 31 | /** 32 | * Defines an Action object with the specified 33 | * description string and a default icon. 34 | */ 35 | public OpenDeviceAction(String name) { 36 | super(name); 37 | } 38 | 39 | /** 40 | * Defines an Action object with the specified 41 | * description string and a the specified icon. 42 | */ 43 | public OpenDeviceAction(String name, Icon icon) { 44 | super(name, icon); 45 | } 46 | 47 | /** 48 | * Invoked when an action occurs. 49 | */ 50 | public void actionPerformed(ActionEvent e) { 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/action/OpenRecordingAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.action; 19 | 20 | import javax.swing.*; 21 | import java.awt.event.ActionEvent; 22 | 23 | public class OpenRecordingAction extends AbstractAction { 24 | /** 25 | * Defines an Action object with a default 26 | * description string and default icon. 27 | */ 28 | public OpenRecordingAction() { 29 | } 30 | 31 | /** 32 | * Defines an Action object with the specified 33 | * description string and a default icon. 34 | */ 35 | public OpenRecordingAction(String name) { 36 | super(name); 37 | } 38 | 39 | /** 40 | * Defines an Action object with the specified 41 | * description string and a the specified icon. 42 | */ 43 | public OpenRecordingAction(String name, Icon icon) { 44 | super(name, icon); 45 | } 46 | 47 | /** 48 | * Invoked when an action occurs. 49 | */ 50 | public void actionPerformed(ActionEvent e) { 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/action/SettingsAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.action; 19 | 20 | import javax.swing.*; 21 | import java.awt.event.ActionEvent; 22 | 23 | public class SettingsAction extends AbstractAction { 24 | /** 25 | * Defines an Action object with a default 26 | * description string and default icon. 27 | */ 28 | public SettingsAction() { 29 | } 30 | 31 | /** 32 | * Defines an Action object with the specified 33 | * description string and a default icon. 34 | */ 35 | public SettingsAction(String name) { 36 | super(name); 37 | } 38 | 39 | /** 40 | * Defines an Action object with the specified 41 | * description string and a the specified icon. 42 | */ 43 | public SettingsAction(String name, Icon icon) { 44 | super(name, icon); 45 | } 46 | 47 | /** 48 | * Invoked when an action occurs. 49 | */ 50 | public void actionPerformed(ActionEvent e) { 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/image/AbstractImageFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.image; 19 | 20 | import java.awt.image.BufferedImage; 21 | import java.beans.PropertyChangeEvent; 22 | import java.beans.PropertyChangeListener; 23 | import java.io.IOException; 24 | 25 | public abstract class AbstractImageFilter implements IImageFilter { 26 | private RenderSettings renderSettings; 27 | 28 | public AbstractImageFilter(RenderSettings renderSettings) { 29 | setRenderSettings(renderSettings); 30 | } 31 | 32 | private PropertyChangeListener renderSettingsChangeListener = new PropertyChangeListener() { 33 | public void propertyChange(PropertyChangeEvent evt) { 34 | updateFilter(); 35 | } 36 | }; 37 | 38 | public RenderSettings getRenderSettings() { 39 | return renderSettings; 40 | } 41 | 42 | public void setRenderSettings(RenderSettings renderSettings) { 43 | if (this.renderSettings != renderSettings) { 44 | if (this.renderSettings != null) { 45 | this.renderSettings.removePropertyChangeListener(renderSettingsChangeListener); 46 | } 47 | 48 | this.renderSettings = renderSettings; 49 | this.renderSettings.addPropertyChangeListener(renderSettingsChangeListener); 50 | updateFilter(); 51 | } 52 | } 53 | 54 | public abstract BufferedImage render(BufferedImage srcImage) throws IOException; 55 | 56 | /** 57 | * Invoked whenever the RenderSettings are updated. 58 | */ 59 | protected abstract void updateFilter(); 60 | } 61 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/image/DeviceScreenImageProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.image; 19 | 20 | import com.android.ddmlib.IDevice; 21 | import com.android.ddmlib.RawImage; 22 | 23 | import java.awt.image.BufferedImage; 24 | import java.io.IOException; 25 | import java.util.ArrayList; 26 | 27 | /** 28 | * Provides device screen capture images after applying any specified image processing filters. 29 | */ 30 | public class DeviceScreenImageProvider implements IImageProvider { 31 | private IDevice device; 32 | private ArrayList imageFilters; 33 | 34 | /** 35 | * Initializes this provider for image capture from the specified device. 36 | * 37 | * @param device The device (or device emulator). 38 | */ 39 | public DeviceScreenImageProvider(IDevice device) { 40 | assert device != null; 41 | this.device = device; 42 | } 43 | 44 | /** 45 | * Adds an image filter to the list of filters to be applied (in add order). 46 | * 47 | * @param imageFilter A filter for image processing; can be added more than once 48 | */ 49 | public void addImageFilter(IImageFilter imageFilter) { 50 | if (imageFilters == null) { 51 | imageFilters = new ArrayList(); 52 | } 53 | 54 | if (imageFilter != null) { 55 | imageFilters.add(imageFilter); 56 | } 57 | } 58 | 59 | /** 60 | * Removes all occurrences of the image filter from the list of filters, if present. 61 | * 62 | * @param imageFilter The filter to be removed. 63 | */ 64 | public void removeImageFilter(IImageFilter imageFilter) { 65 | if (imageFilters == null || imageFilter == null) return; 66 | 67 | boolean removed = false; 68 | 69 | do { 70 | removed = imageFilters.remove(imageFilter); 71 | } while (removed); 72 | 73 | if (imageFilters.isEmpty()) { 74 | imageFilters = null; 75 | } 76 | } 77 | 78 | /** 79 | * Captures a device screen shot, applying any filters that have been added to this provider. 80 | * 81 | * @return BufferedImage, or null if the device frame buffer was only partially read 82 | * @throws IOException 83 | */ 84 | public BufferedImage getImage() throws IOException { 85 | RawImage rawImage = device.getScreenshot(); 86 | 87 | if (rawImage == null) { 88 | // Indicates other problems, such as partial replies from the ADB frame-buffer, 89 | // or an unsupported version of the image format for the current ddmlib 90 | // (have to check log) 91 | return null; 92 | } 93 | 94 | BufferedImage image = new BufferedImage(rawImage.width, rawImage.height, BufferedImage.TYPE_INT_ARGB); 95 | 96 | int index = 0; 97 | int indexInc = rawImage.bpp >> 3; 98 | 99 | for (int y = 0; y < rawImage.height; y++) { 100 | for (int x = 0; x < rawImage.width; x++, index += indexInc) { 101 | int value = rawImage.getARGB(index); 102 | image.setRGB(x, y, value); 103 | } 104 | } 105 | 106 | if (imageFilters != null) { 107 | image = processFilters(image); 108 | } 109 | 110 | return image; 111 | } 112 | 113 | private BufferedImage processFilters(BufferedImage image) throws IOException { 114 | for (IImageFilter filter : imageFilters) { 115 | image = filter.render(image); 116 | } 117 | 118 | return image; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/image/IImageFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.image; 19 | 20 | import java.awt.image.BufferedImage; 21 | import java.io.IOException; 22 | 23 | /** 24 | * Performs some sort of processing on or for an image. The image returned may be 25 | * the original image or a new image. 26 | */ 27 | public interface IImageFilter { 28 | BufferedImage render(BufferedImage srcImage) throws IOException; 29 | } 30 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/image/IImageProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.image; 19 | 20 | import java.awt.image.BufferedImage; 21 | import java.io.IOException; 22 | 23 | public interface IImageProvider { 24 | void addImageFilter(IImageFilter imageFilter); 25 | 26 | void removeImageFilter(IImageFilter imageFilter); 27 | 28 | BufferedImage getImage() throws IOException; 29 | } 30 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/image/Orientation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.image; 19 | 20 | 21 | public enum Orientation { 22 | PORTRAIT, 23 | LANDSCAPE 24 | } 25 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/image/RecordImageFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.image; 19 | 20 | import java.awt.image.BufferedImage; 21 | import java.io.IOException; 22 | 23 | /** 24 | * This filter copies the image to a record location for subsequent playback. 25 | */ 26 | public class RecordImageFilter extends AbstractImageFilter { 27 | private boolean enabled; 28 | private String recordPath; 29 | 30 | public RecordImageFilter(RenderSettings renderSettings) { 31 | super(renderSettings); 32 | } 33 | 34 | public boolean isEnabled() { 35 | return enabled; 36 | } 37 | 38 | public void setEnabled(boolean enabled) { 39 | this.enabled = enabled; 40 | } 41 | 42 | @Override 43 | public BufferedImage render(BufferedImage srcImage) throws IOException { 44 | // TODO: implement 45 | return srcImage; 46 | } 47 | 48 | @Override 49 | protected void updateFilter() { 50 | RenderSettings renderSettings = getRenderSettings(); 51 | if (renderSettings == null) return; 52 | 53 | // this.recordPath = renderSettings.getRecordPath(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/image/RenderSettings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.image; 19 | 20 | import java.beans.PropertyChangeListener; 21 | import java.beans.PropertyChangeSupport; 22 | 23 | public class RenderSettings { 24 | 25 | private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); 26 | 27 | private double scale = 1.5d; 28 | 29 | private Orientation orientation = Orientation.PORTRAIT; 30 | 31 | public void addPropertyChangeListener(PropertyChangeListener listener) { 32 | this.propertyChangeSupport.addPropertyChangeListener(listener); 33 | } 34 | 35 | public void removePropertyChangeListener(PropertyChangeListener listener) { 36 | this.propertyChangeSupport.removePropertyChangeListener(listener); 37 | } 38 | 39 | public PropertyChangeListener[] getPropertyChangeListeners() { 40 | return this.propertyChangeSupport.getPropertyChangeListeners(); 41 | } 42 | 43 | public double getScale() { 44 | return this.scale; 45 | } 46 | 47 | public void setScale(double scale) { 48 | if (this.scale != scale) { 49 | double oldValue = this.scale; 50 | this.scale = scale; 51 | propertyChangeSupport.firePropertyChange("scale", oldValue, scale); 52 | } 53 | } 54 | 55 | public Orientation getOrientation() { 56 | return this.orientation; 57 | } 58 | 59 | public void setOrientation(Orientation orientation) { 60 | if (this.orientation != orientation) { 61 | Orientation oldValue = this.orientation; 62 | this.orientation = orientation; 63 | propertyChangeSupport.firePropertyChange("orientation", oldValue, orientation); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/image/RotateImageFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.image; 19 | 20 | import java.awt.*; 21 | import java.awt.geom.AffineTransform; 22 | import java.awt.geom.Point2D; 23 | import java.awt.image.AffineTransformOp; 24 | import java.awt.image.BufferedImage; 25 | import java.io.IOException; 26 | 27 | /** 28 | * This filter rotates an image as specified by RenderSettings orientation. 29 | */ 30 | public class RotateImageFilter extends AbstractImageFilter { 31 | private AffineTransformOp op; 32 | 33 | public RotateImageFilter(RenderSettings renderSettings) { 34 | super(renderSettings); 35 | } 36 | 37 | @Override 38 | public BufferedImage render(BufferedImage srcImage) throws IOException { 39 | if (op == null) return srcImage; 40 | 41 | return srcImage; 42 | } 43 | 44 | @Override 45 | protected void updateFilter() { 46 | RenderSettings renderSettings = getRenderSettings(); 47 | if (renderSettings == null) { 48 | op = null; 49 | return; 50 | } 51 | } 52 | 53 | private AffineTransform findTranslation(AffineTransform at, BufferedImage bi) { 54 | if (bi == null) return null; 55 | 56 | Point2D p2din, p2dout; 57 | 58 | p2din = new Point2D.Double(0.0, 0.0); 59 | p2dout = at.transform(p2din, null); 60 | double ytrans = p2dout.getY(); 61 | 62 | p2din = new Point2D.Double(0, bi.getHeight()); 63 | p2dout = at.transform(p2din, null); 64 | double xtrans = p2dout.getX(); 65 | 66 | AffineTransform tat = new AffineTransform(); 67 | tat.translate(-xtrans, -ytrans); 68 | return tat; 69 | } 70 | 71 | private double orientationToRadians(Orientation orientation) { 72 | double degrees = orientation == orientation.LANDSCAPE ? -90 : 0; 73 | return degreesToRadians(degrees); 74 | } 75 | 76 | /** 77 | * Convert degrees to radians. 78 | * 79 | * @param rotationAngle in degrees. Positive degrees rotate in a clockwise direction; negative, counter-clockewise. 80 | * @return 81 | */ 82 | private double degreesToRadians(double rotationAngle) { 83 | return rotationAngle * Math.PI / 180.0; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/image/ScaleImageFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.image; 19 | 20 | import java.awt.*; 21 | import java.awt.geom.AffineTransform; 22 | import java.awt.image.AffineTransformOp; 23 | import java.awt.image.BufferedImage; 24 | import java.io.IOException; 25 | 26 | /** 27 | * This filter scales an image as specified by RenderSettings scale. 28 | */ 29 | public class ScaleImageFilter extends AbstractImageFilter { 30 | private AffineTransformOp op; 31 | 32 | public ScaleImageFilter(RenderSettings renderSettings) { 33 | super(renderSettings); 34 | } 35 | 36 | @Override 37 | public BufferedImage render(BufferedImage srcImage) throws IOException { 38 | return (op != null) ? op.filter(srcImage, null) : srcImage; 39 | } 40 | 41 | @Override 42 | protected void updateFilter() { 43 | RenderSettings renderSettings = getRenderSettings(); 44 | if (renderSettings == null) return; 45 | 46 | double scale = renderSettings.getScale(); 47 | AffineTransform tx = AffineTransform.getScaleInstance(scale, scale); 48 | 49 | op = new AffineTransformOp( 50 | tx, 51 | new RenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/ui/DeviceScreenView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.ui; 19 | 20 | import com.commonsware.droidex.image.IImageProvider; 21 | 22 | import javax.swing.*; 23 | import java.awt.*; 24 | import java.awt.image.BufferedImage; 25 | import java.io.IOException; 26 | 27 | public class DeviceScreenView extends JPanel { 28 | public static final int MAX_FRAMERATE = 20; 29 | private IImageProvider imageProvider; 30 | private int frameRate; 31 | private boolean stopRequested; 32 | private Thread playThread; 33 | private Object monitor = new Object(); 34 | 35 | public DeviceScreenView() { 36 | } 37 | 38 | public DeviceScreenView(IImageProvider imageProvider) { 39 | setImageProvider(imageProvider); 40 | } 41 | 42 | public int getFrameRate() { 43 | synchronized (monitor) { 44 | return this.frameRate; 45 | } 46 | } 47 | 48 | public void setFrameRate(int frameRate) { 49 | if (frameRate >= 0 && frameRate <= MAX_FRAMERATE && frameRate != this.frameRate) { 50 | synchronized (monitor) { 51 | this.frameRate = frameRate; 52 | monitor.notify(); 53 | } 54 | } 55 | } 56 | 57 | public void play() { 58 | stopRequested = false; 59 | 60 | if (playThread == null) { 61 | playThread = new Thread(new Runnable() { 62 | public void run() { 63 | while (!stopRequested) { 64 | if (getFrameRate() == 0) { 65 | try { 66 | synchronized (monitor) { 67 | monitor.wait(); 68 | } 69 | } catch (InterruptedException e) { 70 | // notified 71 | } 72 | } 73 | int frameRate = getFrameRate(); 74 | if (frameRate > 0 && !stopRequested) { 75 | repaint(); 76 | try { 77 | Thread.sleep(1000L / frameRate); // frameRate guarranted != 0 78 | } catch (Throwable t) { 79 | // woken up 80 | } 81 | } 82 | } 83 | playThread = null; 84 | } 85 | }); 86 | 87 | playThread.start(); 88 | } 89 | } 90 | 91 | public void stop() { 92 | stopRequested = true; 93 | } 94 | 95 | public void setImageProvider(IImageProvider imageProvider) { 96 | this.imageProvider = imageProvider; 97 | 98 | try { 99 | BufferedImage image = imageProvider.getImage(); 100 | setPreferredSize(new Dimension(image.getWidth(), image.getHeight())); 101 | } 102 | catch (IOException e) { 103 | System.err.println("Exception fetching image: " + e.toString()); 104 | } 105 | } 106 | 107 | protected void paintComponent(Graphics g) { 108 | if (imageProvider == null) { 109 | super.paintComponent(g); 110 | return; 111 | } 112 | 113 | try { 114 | BufferedImage image = imageProvider.getImage(); 115 | 116 | if (image != null) { 117 | setPreferredSize(new Dimension(image.getWidth(), image.getHeight())); 118 | int x = (getWidth() - image.getWidth()) / 2; 119 | int y = (getHeight() - image.getHeight()) / 2; 120 | g.drawImage(image, x, y, this); 121 | } 122 | } 123 | catch (IOException e) { 124 | System.err.println("Exception fetching image: " + e.toString()); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/ui/DroidExMenuBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.ui; 19 | 20 | import com.commonsware.droidex.Actions; 21 | 22 | import javax.swing.*; 23 | 24 | public class DroidExMenuBar extends JMenuBar { 25 | public DroidExMenuBar() 26 | { 27 | initFileMenu(); 28 | initEditMenu(); 29 | initHelpMenu(); 30 | } 31 | 32 | void initFileMenu() 33 | { 34 | JMenu menu = new JMenu("File"); 35 | menu.setMnemonic('F'); 36 | this.add(menu); 37 | 38 | JMenuItem item; 39 | 40 | item = menu.add(Actions.OpenDeviceAction); 41 | item = menu.add(Actions.OpenRecordingAction); 42 | menu.addSeparator(); 43 | 44 | item = menu.add(Actions.SettingsAction); 45 | menu.addSeparator(); 46 | 47 | item = menu.add(Actions.ExitAction); 48 | } 49 | 50 | void initEditMenu() 51 | { 52 | JMenu menu = new JMenu("Edit"); 53 | menu.setMnemonic('E'); 54 | this.add(menu); 55 | 56 | } 57 | 58 | void initHelpMenu() 59 | { 60 | JMenu menu = new JMenu("Help"); 61 | menu.setMnemonic('H'); 62 | this.add(menu); 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/com/commonsware/droidex/ui/DroidExToolBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2009 CommonsWare, LLC 3 | * Portions Copyright (C) 2007-2008 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.commonsware.droidex.ui; 19 | 20 | import com.commonsware.droidex.Actions; 21 | 22 | import javax.swing.*; 23 | 24 | public class DroidExToolBar extends JToolBar { 25 | public DroidExToolBar() 26 | { 27 | add(Actions.OpenDeviceAction); 28 | add(Actions.OpenRecordingAction); 29 | } 30 | } 31 | --------------------------------------------------------------------------------