/** * Copyright (c) Microsoft Corporation * <p/> * All rights reserved. * <p/> * MIT License * <p/> * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated * documentation files (the "Software"), to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and * to permit persons to whom the Software is furnished to do so, subject to the following conditions: * <p/> * The above copyright notice and this permission notice shall be included in all copies or substantial portions of * the Software. * <p/> * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.microsoft.intellij.activitylog; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.BrowserHyperlinkListener; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.table.TableView; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ListTableModel; import com.intellij.util.ui.PlatformColors; import com.microsoft.intellij.AzurePlugin; import com.microsoft.intellij.util.PluginUtil; import com.microsoftopentechnologies.azurecommons.deploy.DeploymentEventArgs; import com.microsoftopentechnologies.azurecommons.deploy.DeploymentEventListener; import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.table.TableCellRenderer; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.font.TextAttribute; import java.io.IOException; import java.net.URI; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.Locale; import java.util.Map; import static com.microsoft.intellij.ui.messages.AzureBundle.message; public class ActivityLogToolWindowFactory implements ToolWindowFactory { public static final String ACTIVITY_LOG_WINDOW = "Azure Activity Log"; private SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss", Locale.getDefault()); private TableView<DeploymentTableItem> table; private HashMap<String, DeploymentTableItem> rows = new HashMap<String, DeploymentTableItem>(); private Project project; @Override public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) { this.project = project; table = new TableView<DeploymentTableItem>(new ListTableModel<DeploymentTableItem>(DESC, PROGRESS, STATUS, START_TIME)); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // add mouse listener for links in table table.addMouseListener(createTableMouseListener()); toolWindow.getComponent().add(new JBScrollPane(table)); registerDeploymentListener(); } private MouseListener createTableMouseListener() { return new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (table.getSelectedColumn() == 2) { DeploymentTableItem item = table.getSelectedObject(); if (item != null && item.link != null) { try { Desktop.getDesktop().browse(URI.create(item.link)); } catch (IOException e1) { PluginUtil.displayErrorDialogAndLog(message("error"), message("error"), e1); } } } } }; } public void registerDeploymentListener() { AzurePlugin.addDeploymentEventListener( new DeploymentEventListener() { @Override public void onDeploymentStep(final DeploymentEventArgs args) { // unique identifier for deployment String key = args.getId() + args.getStartTime().getTime(); if (rows.containsKey(key)) { final DeploymentTableItem item = rows.get(key); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { item.progress += args.getDeployCompleteness(); if (args.getDeployMessage().equalsIgnoreCase(message("runStatus"))) { String html = String.format("%s%s%s%s", " ", "<html><a href=\"" + args.getDeploymentURL() + "\">", message("runStatusVisible"), "</a></html>"); item.description = message("runStatusVisible"); item.link = args.getDeploymentURL(); if (!ToolWindowManager.getInstance(project).getToolWindow(ActivityLogToolWindowFactory.ACTIVITY_LOG_WINDOW).isVisible()) { ToolWindowManager.getInstance(project).notifyByBalloon(ACTIVITY_LOG_WINDOW, MessageType.INFO, html, null, new BrowserHyperlinkListener()); } } else { item.description = args.getDeployMessage(); } table.getListTableModel().fireTableDataChanged(); } }); } else { final DeploymentTableItem item = new DeploymentTableItem(args.getId(), args.getDeployMessage(), dateFormat.format(args.getStartTime()), args.getDeployCompleteness()); rows.put(key, item); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { table.getListTableModel().addRow(item); } }); } } }); } private class ProgressBarRenderer implements TableCellRenderer { private final JProgressBar progressBar = new JProgressBar(); private final JLabel label = new JLabel(); public ProgressBarRenderer() { progressBar.setMaximum(100); } @Override public Component getTableCellRendererComponent(@NotNull JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if ((Integer) value < 100) { progressBar.setValue((Integer) value); return progressBar; } else { label.setText(""); return label; } } } private class LinkRenderer implements TableCellRenderer { private final JLabel label = new JLabel(); public LinkRenderer() { label.setForeground(PlatformColors.BLUE); Font font = label.getFont(); Map attributes = font.getAttributes(); attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); label.setFont(font.deriveFont(attributes)); } @Override public Component getTableCellRendererComponent(@NotNull JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { label.setText((String) value); return label; } } private final ColumnInfo<DeploymentTableItem, String> DESC = new ColumnInfo<DeploymentTableItem, String>(message("desc")) { public String valueOf(DeploymentTableItem object) { return object.deploymentId; } }; private final ColumnInfo<DeploymentTableItem, Integer> PROGRESS = new ColumnInfo<DeploymentTableItem, Integer>("Progress") { private TableCellRenderer renderer = new ProgressBarRenderer(); public Integer valueOf(DeploymentTableItem object) { return object.progress; } public TableCellRenderer getRenderer(DeploymentTableItem object) { return renderer; } }; private final ColumnInfo<DeploymentTableItem, String> STATUS = new ColumnInfo<DeploymentTableItem, String>(message("status")) { private TableCellRenderer renderer = new LinkRenderer(); public String valueOf(DeploymentTableItem object) { return object.description; } public TableCellRenderer getRenderer(DeploymentTableItem object) { if (object.link != null) { return renderer; } else { return super.getRenderer(object); } } }; private final ColumnInfo<DeploymentTableItem, String> START_TIME = new ColumnInfo<DeploymentTableItem, String>(message("startTime")) { public String valueOf(DeploymentTableItem object) { return object.startDate; } }; private class DeploymentTableItem { private String deploymentId; private String description; private String startDate; private String link; private int progress; public DeploymentTableItem(String deploymentId, String description, String startDate, int progress) { this.deploymentId = deploymentId; this.description = description; this.startDate = startDate; this.progress = progress; } } }