1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package com.update.check.action.view; 17 18 import com.intellij.openapi.project.Project; 19 import com.intellij.openapi.ui.DialogWrapper; 20 import com.intellij.ui.JBColor; 21 import org.jetbrains.annotations.NotNull; 22 import org.jetbrains.annotations.Nullable; 23 import javax.swing.JTable; 24 import javax.swing.JPanel; 25 import javax.swing.JComponent; 26 import javax.swing.event.MouseInputListener; 27 import javax.swing.table.AbstractTableModel; 28 import javax.swing.table.DefaultTableCellRenderer; 29 import java.awt.Component; 30 import java.awt.Cursor; 31 import java.awt.Rectangle; 32 import java.awt.Point; 33 import java.awt.Desktop; 34 import java.awt.event.ActionEvent; 35 import java.awt.event.MouseEvent; 36 import java.io.IOException; 37 import java.net.URISyntaxException; 38 import java.net.URL; 39 import java.util.List; 40 import java.util.Map; 41 import java.util.HashMap; 42 import java.util.ArrayList; 43 import java.util.Arrays; 44 45 /** 46 * ShowChangeLogsDialog 47 * 48 * @since 23-04-07 49 */ 50 public class ShowChangeLogsDialog extends DialogWrapper { 51 private JTable showChangeLogs; 52 53 private JPanel rootPanel; 54 55 private Project project; 56 57 private Map<String, String> changeLogs = new HashMap<>(); 58 59 private List<String> changeVersions = new ArrayList<>(); 60 61 /** 62 * ShowChangeLogsDialog 63 * 64 * @param project project 65 * @param changeLogs changelogs 66 * @param changeVersions change version 67 */ ShowChangeLogsDialog(@otNull Project project, Map<String, String> changeLogs, String changeVersions)68 public ShowChangeLogsDialog(@NotNull Project project, Map<String, String> changeLogs, String changeVersions) { 69 super(project, false); 70 this.project = project; 71 this.changeLogs = changeLogs; 72 this.changeVersions.addAll(Arrays.asList(changeVersions.split(","))); 73 this.setTitle(ConstString.get("view.changes.url")); 74 Report report = new Report(); 75 this.showChangeLogs.setModel(report); 76 LinkCellRenderer renderer = new LinkCellRenderer(); 77 this.showChangeLogs.setDefaultRenderer(Object.class, renderer); 78 this.showChangeLogs.addMouseListener(renderer); 79 this.showChangeLogs.addMouseMotionListener(renderer); 80 this.init(); 81 } 82 83 /** 84 * ShowChangeLogsDialog 85 * 86 * @param project project 87 * @param canBeParent canBeParent 88 */ ShowChangeLogsDialog(@ullable Project project, boolean canBeParent)89 protected ShowChangeLogsDialog(@Nullable Project project, boolean canBeParent) { 90 super(project, canBeParent); 91 } 92 93 /** 94 * createCenterPanel 95 * 96 * @return this rootPanel 97 */ 98 @Override createCenterPanel()99 protected JComponent createCenterPanel() { 100 return this.rootPanel; 101 } 102 onCancel(@ullable ActionEvent event)103 private void onCancel(@Nullable ActionEvent event) { 104 super.doCancelAction(); 105 dispose(); 106 } 107 108 @Override doCancelAction()109 public void doCancelAction() { 110 this.onCancel(null); 111 } 112 113 /** 114 * LinkCellRenderer 115 * 116 * @since 23-04-07 117 */ 118 static class LinkCellRenderer extends DefaultTableCellRenderer implements MouseInputListener { 119 private int row = -1; 120 private int col = -1; 121 private JTable table = null; 122 123 @Override getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)124 public Component getTableCellRendererComponent(JTable table, Object value, 125 boolean isSelected, boolean hasFocus, int row, int column) { 126 this.table = table; 127 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 128 table.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 129 this.setText(value.toString()); 130 if (row == this.row && column == this.col) { 131 if (column == 1) { 132 this.setForeground(JBColor.BLUE); 133 table.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 134 this.setText("<html><u>" + value + "</u></html>"); 135 } 136 setBackground(table.getSelectionBackground()); 137 } else if (isSelected) { 138 setForeground(table.getSelectionForeground()); 139 setBackground(table.getSelectionBackground()); 140 } else { 141 setBackground(JBColor.WHITE); 142 } 143 return this; 144 } 145 146 /** 147 * Invoked when the mouse exits a component. 148 * 149 * @param e the event to be processed 150 */ mouseExited(MouseEvent e)151 public void mouseExited(MouseEvent e) { 152 if (table != null) { 153 int oldRow = row; 154 int oldCol = col; 155 row = -1; 156 col = -1; 157 if (oldRow != -1 && oldCol != -1) { 158 Rectangle rect = table.getCellRect(oldRow, oldCol, false); 159 table.repaint(rect); 160 } 161 } 162 } 163 164 /** 165 * Invoked when a mouse button is pressed on a component and then 166 * dragged. {@code MOUSE_DRAGGED} events will continue to be 167 * delivered to the component where the drag originated until the 168 * mouse button is released (regardless of whether the mouse position 169 * is within the bounds of the component). 170 * <p> 171 * Due to platform-dependent Drag&Drop implementations, 172 * {@code MOUSE_DRAGGED} events may not be delivered during a native 173 * Drag&Drop operation. 174 * 175 * @param e the event to be processed 176 */ mouseDragged(MouseEvent e)177 public void mouseDragged(MouseEvent e) { 178 mouseMoved(e); 179 } 180 181 /** 182 * Invoked when the mouse cursor has been moved onto a component 183 * but no buttons have been pushed. 184 * 185 * @param e the event to be processed 186 */ mouseMoved(MouseEvent e)187 public void mouseMoved(MouseEvent e) { 188 if (table != null) { 189 Point p = e.getPoint(); 190 int oldRow = row; 191 int oldCol = col; 192 row = table.rowAtPoint(p); 193 col = table.columnAtPoint(p); 194 if (oldRow != -1 && oldCol != -1) { 195 Rectangle rect = table.getCellRect(oldRow, oldCol, false); 196 table.repaint(rect); 197 } 198 if (row != -1 && col != -1) { 199 Rectangle rect = table.getCellRect(row, col, false); 200 table.repaint(rect); 201 } 202 } 203 } 204 205 /** 206 * mouse click event 207 * 208 * @param e the event to be processed 209 */ mouseClicked(MouseEvent e)210 public void mouseClicked(MouseEvent e) { 211 Point p = e.getPoint(); 212 int c = table.columnAtPoint(p); 213 if (c != 1) { 214 return; 215 } 216 int r = table.rowAtPoint(p); 217 URL url = null; 218 try { 219 url = new URL(table.getValueAt(r, c).toString()); 220 Desktop.getDesktop().browse(url.toURI()); 221 } catch (IOException | URISyntaxException ex) { 222 ex.printStackTrace(); 223 } 224 } 225 226 /** 227 * Invoked when a mouse button has been pressed on a component. 228 * 229 * @param e the event to be processed 230 */ mousePressed(MouseEvent e)231 public void mousePressed(MouseEvent e) { 232 e.getClickCount(); 233 } 234 235 /** 236 * Invoked when a mouse button has been released on a component. 237 * 238 * @param e the event to be processed 239 */ mouseReleased(MouseEvent e)240 public void mouseReleased(MouseEvent e) { 241 e.getClickCount(); 242 } 243 244 /** 245 * Invoked when the mouse enters a component. 246 * 247 * @param e the event to be processed 248 */ mouseEntered(MouseEvent e)249 public void mouseEntered(MouseEvent e) { 250 e.getClickCount(); 251 } 252 } 253 254 /** 255 * Report 256 * 257 * @since 23-04-07 258 */ 259 class Report extends AbstractTableModel { 260 List<Object[]> dataList = new ArrayList<>(); 261 String[] titles = new String[3]; 262 int sum = changeVersions.size(); 263 264 /** 265 * Report 266 * 267 * @since 23-04-07 268 */ Report()269 public Report() { 270 for (int i = 0; i < sum; i++) { 271 dataList.add(new Object[]{changeVersions.get(i), changeLogs.get(changeVersions.get(i))}); 272 } 273 titles[0] = ConstString.get("sdk.version"); 274 titles[1] = ConstString.get("changelog.url"); 275 } 276 277 @Override isCellEditable(int row, int col)278 public boolean isCellEditable(int row, int col) { 279 return col == 0; 280 } 281 282 @Override getColumnName(int column)283 public String getColumnName(int column) { 284 return titles[column]; 285 } 286 287 @Override getRowCount()288 public int getRowCount() { 289 return sum; 290 } 291 292 @Override getColumnCount()293 public int getColumnCount() { 294 return 2; 295 } 296 297 @Override getValueAt(int rowIndex, int columnIndex)298 public Object getValueAt(int rowIndex, int columnIndex) { 299 return this.dataList.get(rowIndex)[columnIndex]; 300 } 301 302 @Override setValueAt(Object aValue, int rowIndex, int columnIndex)303 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 304 this.dataList.get(rowIndex)[columnIndex] = aValue; 305 } 306 307 } 308 309 /** 310 * showDialog 311 * 312 * @param project project 313 * @param changeLogs changeLogs 314 * @param changeVersions changeVersions 315 */ showDialog(Project project, Map<String, String> changeLogs, String changeVersions)316 public static void showDialog(Project project, Map<String, 317 String> changeLogs, String changeVersions) { 318 ShowChangeLogsDialog showChangeLogsDialog = new ShowChangeLogsDialog(project, changeLogs, changeVersions); 319 showChangeLogsDialog.show(); 320 } 321 } 322