1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.atest.toolWindow; 17 18 import com.android.atest.AtestUtils; 19 import com.android.atest.Constants; 20 import com.android.atest.commandAdapter.CommandRunner; 21 import com.android.atest.dialog.MessageDialog; 22 import com.android.atest.widget.AtestFastInputController; 23 import com.android.atest.widget.AtestNotification; 24 import com.intellij.notification.Notifications; 25 import com.intellij.openapi.diagnostic.Logger; 26 import com.intellij.openapi.project.Project; 27 import com.intellij.openapi.wm.ToolWindow; 28 import com.intellij.openapi.wm.ToolWindowManager; 29 import com.intellij.openapi.wm.ex.ToolWindowEx; 30 import com.intellij.openapi.wm.impl.ToolWindowImpl; 31 import org.jetbrains.annotations.NotNull; 32 33 import javax.swing.*; 34 import java.awt.*; 35 36 /** UI content of Atest tool window. */ 37 public class AtestToolWindow { 38 39 private static final int INITIAL_WIDTH = 1000; 40 private static final Logger LOG = Logger.getInstance(AtestToolWindow.class); 41 private static AtestToolWindow sAtestToolWindowInstance; 42 43 private JPanel mAtestToolWindowPanel; 44 private JScrollPane mScorll; 45 private JLabel mAtestlabel; 46 private JTextField mLunchTarget; 47 private JCheckBox mRunOnHost; 48 private JCheckBox mTestMapping; 49 private JCheckBox mSkipBuild; 50 private JButton mRunButton; 51 private JComboBox mTestTarget; 52 private JButton mStopButton; 53 private Project mProject; 54 55 /** 56 * Initializes AtestToolWindow with ToolWindow and Project. 57 * 58 * @param toolWindow a child window of the IDE used to display information. 59 * @param project the current intelliJ project. 60 */ AtestToolWindow(ToolWindow toolWindow, Project project)61 private AtestToolWindow(ToolWindow toolWindow, Project project) { 62 mProject = project; 63 String basePath = project.getBasePath(); 64 setInitialWidth((ToolWindowEx) toolWindow); 65 setRunButton(basePath); 66 setStopButton(); 67 initTestTarget(basePath); 68 AtestFastInputController fastInputController = 69 new AtestFastInputController(mTestTarget, mRunOnHost, mTestMapping, mSkipBuild); 70 fastInputController.linkCheckBoxWithTestTarget(); 71 } 72 73 /** 74 * Initializes AtestToolWindow instance. 75 * 76 * <p>Because the AtestToolWindow should be modified when the project is changed. It can't be 77 * singleton. This initializer is used by the ToolWindowFactory. We use IntelliJ's mechanism to 78 * make sure AtestToolWindow's instance can always follow the project. 79 * 80 * @param toolWindow a child window of the IDE used to display information. 81 * @param project the current intelliJ project. 82 * @return the AtestToolWindow instance. 83 */ 84 @NotNull initAtestToolWindow(ToolWindow toolWindow, Project project)85 public static AtestToolWindow initAtestToolWindow(ToolWindow toolWindow, Project project) { 86 sAtestToolWindowInstance = new AtestToolWindow(toolWindow, project); 87 return sAtestToolWindowInstance; 88 } 89 90 /** 91 * Gets AtestToolWindow instance by project. 92 * 93 * <p>When using ToolWindowManager to get atest tool window, it will initialize the 94 * AtestToolWindow by {@link AtestToolWindowFactory} asynchronously. We use 95 * ensureContentInitialized from ToolWindowImpl to ensure the AtestToolWindow has been 96 * initialized. 97 * 98 * @param project the current intelliJ project. 99 * @return the AtestToolWindow instance. 100 */ 101 @NotNull getInstance(@otNull Project project)102 public static AtestToolWindow getInstance(@NotNull Project project) { 103 ToolWindow AtestTW = 104 ToolWindowManager.getInstance(project).getToolWindow(Constants.ATEST_TOOL_WINDOW); 105 if (AtestTW instanceof ToolWindowImpl) { 106 ((ToolWindowImpl) AtestTW).ensureContentInitialized(); 107 } 108 109 if (sAtestToolWindowInstance == null) { 110 LOG.error("AtestToolWindowInstance is null when getting instance by project"); 111 Notifications.Bus.notify(new AtestNotification(Constants.ATEST_WINDOW_FAIL)); 112 } 113 return sAtestToolWindowInstance; 114 } 115 116 /** 117 * Initializes mTestTarget. 118 * 119 * @param basePath a string that represents current project's base path. 120 */ initTestTarget(String basePath)121 private void initTestTarget(String basePath) { 122 mTestTarget.setEditable(true); 123 if (AtestUtils.hasTestMapping(basePath)) { 124 mTestTarget.setSelectedItem(basePath); 125 } 126 } 127 128 /** 129 * Sets the initial width of the tool window. 130 * 131 * @param toolWindowEx a toolWindow which has more methods. 132 */ setInitialWidth(@otNull ToolWindowEx toolWindowEx)133 private void setInitialWidth(@NotNull ToolWindowEx toolWindowEx) { 134 int width = toolWindowEx.getComponent().getWidth(); 135 if (width < INITIAL_WIDTH) { 136 toolWindowEx.stretchWidth(INITIAL_WIDTH - width); 137 } 138 } 139 140 /** Initializes the run button. */ setRunButton(String basePath)141 private void setRunButton(String basePath) { 142 // When command running, the run button will be set to disable, then the focus will set to 143 // next object. Set run button not focusable to prevent it. 144 mRunButton.setFocusable(false); 145 mRunButton.addActionListener( 146 e -> { 147 String lunchTarget = mLunchTarget.getText(); 148 String testTarget = mTestTarget.getEditor().getItem().toString(); 149 String workPath = AtestUtils.getAndroidRoot(basePath); 150 try { 151 CommandRunner runner = 152 new CommandRunner( 153 lunchTarget, 154 testTarget, 155 workPath, 156 AtestToolWindow.this, 157 mProject); 158 runner.run(); 159 } catch (IllegalArgumentException exception) { 160 String errorMessage = 161 AtestUtils.checkError(lunchTarget, testTarget, workPath); 162 MessageDialog.showMessageDialog(errorMessage); 163 } 164 }); 165 } 166 167 /** Initializes the stop button. */ setStopButton()168 private void setStopButton() { 169 mStopButton.addActionListener( 170 e -> { 171 CommandRunner.stopProcess(mProject); 172 }); 173 } 174 175 /** Scrolls the output window scroll bar to the bottom. */ scrollToEnd()176 public void scrollToEnd() { 177 JScrollBar vertical = mScorll.getVerticalScrollBar(); 178 vertical.setValue(vertical.getMaximum()); 179 } 180 181 /** 182 * Enables (or disables) the run button. 183 * 184 * @param isEnable true to enable the run button, otherwise disable it. 185 */ setRunEnable(boolean isEnable)186 public void setRunEnable(boolean isEnable) { 187 mRunButton.setEnabled(isEnable); 188 } 189 190 /** 191 * Gets the UI panel of Atest tool window. 192 * 193 * @return the JPanel of Atest tool window. 194 */ getContent()195 public JPanel getContent() { 196 return mAtestToolWindowPanel; 197 } 198 199 /** 200 * Sets the test target of Atest tool window. 201 * 202 * @param target the test target of Atest tool window. 203 */ setTestTarget(@otNull String target)204 public void setTestTarget(@NotNull String target) { 205 mTestTarget.setSelectedItem(target); 206 } 207 208 /** 209 * Sets the lunch target of Atest tool window. 210 * 211 * @param target the lunch target of Atest tool window. 212 */ setLunchTarget(@otNull String target)213 public void setLunchTarget(@NotNull String target) { 214 mLunchTarget.setText(target); 215 } 216 } 217