Merge branch 'develar/ll'

This commit is contained in:
Vladimir Krivosheev
2016-09-07 12:14:44 +02:00
26 changed files with 546 additions and 636 deletions
+9
View File
@@ -32,6 +32,15 @@
<option name="FORMATTER_TAGS_ENABLED" value="true" />
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
<option name="BLOCK_COMMENT_AT_FIRST_COLUMN" value="false" />
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" withSubpackages="false" static="false" />
<package name="com.intellij.ui.layout" withSubpackages="true" static="false" />
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
</value>
</option>
</JetCodeStyleSettings>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
@@ -20,6 +20,7 @@ import com.intellij.icons.AllIcons;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.ComponentsKt;
import com.intellij.ui.layout.LayoutKt;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -96,6 +97,6 @@ class EnterPasswordComponent {
note = "The passwords will be stored in IDE configuration files with weak protection<br>(" + subNote + ").";
}
myPromptLabel = LayoutKt.htmlComponent("Master password is required to convert saved passwords.<br>" + note, UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
myPromptLabel = ComponentsKt.htmlComponent("Master password is required to convert saved passwords.<br>" + note, UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
}
}
@@ -54,7 +54,8 @@ class Credentials(user: String?, val password: OneTimeString? = null) {
fun CredentialAttributes(requestor: Class<*>, userName: String?) = CredentialAttributes(requestor.name, userName, requestor)
fun Credentials?.isFulfilled() = this != null && userName != null && password != null
fun Credentials?.isFulfilled() = this != null && userName != null && !password.isNullOrEmpty()
fun Credentials?.hasOnlyUserName() = this != null && userName != null && password.isNullOrEmpty()
fun Credentials?.isEmpty() = this == null || (userName == null && password == null)
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,6 +48,7 @@ public abstract class ErrorReportSubmitter implements PluginAware {
/**
* @return an action text to be used in Error Reporter user interface, e.g. "Report to JetBrains".
*/
@NotNull
public abstract String getReportActionText();
/**
@@ -15,19 +15,35 @@
*/
package com.intellij.openapi.ui
import com.intellij.openapi.project.Project
import java.awt.Component
import javax.swing.JComponent
fun dialog(title: String, centerPanel: JComponent, resizable: Boolean = true, preferedFocusComponent: JComponent? = null, okActionEnabled: Boolean = true): DialogBuilder {
val builder = DialogBuilder()
fun dialog(title: String,
centerPanel: JComponent,
resizable: Boolean = false,
preferedFocusComponent: JComponent? = null,
okActionEnabled: Boolean = true,
project: Project? = null,
parent: Component? = null,
ok: (() -> Unit)? = null): DialogBuilder {
val builder = if (parent == null) DialogBuilder(project) else DialogBuilder(parent)
builder
.title(title)
.centerPanel(centerPanel)
.setPreferredFocusComponent(preferedFocusComponent)
if (!resizable) {
builder.resizable(false)
}
builder.resizable(resizable)
if (!okActionEnabled) {
builder.okActionEnabled(false)
}
if (ok != null) {
builder.setOkOperation {
if (builder.dialogWrapper.okAction.isEnabled) {
ok()
builder.dialogWrapper.close(DialogWrapper.OK_EXIT_CODE)
}
}
}
return builder
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import com.intellij.ui.UI;
import com.intellij.util.ui.JBRectangle;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.accessibility.ScreenReader;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -34,7 +35,6 @@ import javax.accessibility.AccessibleRole;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.HashSet;
import java.util.Set;
/**
@@ -46,7 +46,7 @@ public class LinkLabel<T> extends JLabel {
private LinkListener<T> myLinkListener;
private T myLinkData;
private static final Set<String> ourVisitedLinks = new HashSet<>();
private static final Set<String> ourVisitedLinks = new THashSet<>();
private boolean myIsLinkActive;
@@ -69,6 +69,16 @@ public class LinkLabel<T> extends JLabel {
this(text, icon, aListener, null, null);
}
@NotNull
public static LinkLabel<?> create(@Nullable String text, @Nullable Runnable action) {
return new LinkLabel<>(text, null, action == null ? null : new LinkListener<Object>() {
@Override
public void linkSelected(LinkLabel source, Object linkData) {
action.run();
}
}, null, null);
}
public LinkLabel(String text, @Nullable Icon icon, @Nullable LinkListener<T> aListener, @Nullable T aLinkData) {
this(text, icon, aListener, aLinkData, null);
}
@@ -142,8 +152,12 @@ public class LinkLabel<T> extends JLabel {
try {
myClickIsBeingProcessed = true;
if (myLinkListener != null) myLinkListener.linkSelected(this, myLinkData);
ourVisitedLinks.add(myVisitedLinksKey);
if (myLinkListener != null) {
myLinkListener.linkSelected(this, myLinkData);
}
if (myVisitedLinksKey != null) {
ourVisitedLinks.add(myVisitedLinksKey);
}
repaint();
}
finally {
@@ -222,7 +236,6 @@ public class LinkLabel<T> extends JLabel {
}
protected void onSetActive(boolean active) {
}
private final JBRectangle iconR = new JBRectangle();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,13 +17,11 @@ package com.intellij.ui.components.labels;
import org.jetbrains.annotations.NotNull;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.beans.EventHandler;
import java.beans.PropertyChangeListener;
import static java.beans.EventHandler.create;
/**
* @author Sergey.Malenkov
*/
@@ -35,7 +33,7 @@ public class SwingActionLink extends LinkLabel<Action> implements LinkListener<A
setToolTipText((String)action.getValue(Action.SHORT_DESCRIPTION));
setVisible(action.isEnabled());
setListener(this, action);
action.addPropertyChangeListener(create(PropertyChangeListener.class, this, "visible", "source.enabled"));
action.addPropertyChangeListener(EventHandler.create(PropertyChangeListener.class, this, "visible", "source.enabled"));
}
@Override
@@ -1,18 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.util.net.AuthenticationPanel">
<grid id="54d96" binding="myMainPanel" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="54d96" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="10" bottom="10" right="10"/>
<constraints>
<xy x="111" y="126" width="254" height="120"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3"/>
<xy x="111" y="126" width="254" height="131"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="30b8c" class="javax.swing.JLabel" binding="myDescriptionLabel">
<constraints>
<xy x="10" y="13" width="234" height="14"/>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="1"/>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="##"/>
@@ -20,8 +18,7 @@
</component>
<component id="2c164" class="javax.swing.JLabel">
<constraints>
<xy x="10" y="65" width="54" height="14"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/CommonBundle" key="editbox.password"/>
@@ -29,8 +26,7 @@
</component>
<component id="5918" class="javax.swing.JPasswordField" binding="myPasswordTextField">
<constraints>
<xy x="74" y="62" width="170" height="20"/>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
@@ -38,8 +34,7 @@
</component>
<component id="c345b" class="javax.swing.JTextField" binding="myLoginTextField">
<constraints>
<xy x="74" y="36" width="170" height="20"/>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
@@ -47,8 +42,7 @@
</component>
<component id="537de" class="javax.swing.JLabel">
<constraints>
<xy x="10" y="39" width="33" height="14"/>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0"/>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/CommonBundle" key="editbox.login"/>
@@ -56,8 +50,7 @@
</component>
<component id="94544" class="javax.swing.JCheckBox" binding="rememberPasswordCheckBox">
<constraints>
<xy x="10" y="88" width="126" height="22"/>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0"/>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/CommonBundle" key="checkbox.remember.password"/>
@@ -16,7 +16,10 @@
package com.intellij.util
import com.intellij.openapi.util.text.StringUtil
import java.util.Base64
fun String?.nullize(nullizeSpaces: Boolean = false): String? = StringUtil.nullize(this, nullizeSpaces)
fun String.trimMiddle(maxLength: Int): String? = StringUtil.trimMiddle(this, maxLength)
fun String.trimMiddle(maxLength: Int): String? = StringUtil.trimMiddle(this, maxLength)
fun String.decodeBase64(): ByteArray = Base64.getDecoder().decode(this)
@@ -1,57 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.diagnostic;
import com.intellij.credentialStore.CredentialAttributes;
import com.intellij.credentialStore.Credentials;
import com.intellij.ide.passwordSafe.PasswordSafe;
import com.intellij.openapi.components.*;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.Nullable;
import java.util.Base64;
@State(name = "ErrorReportConfigurable", storages = @Storage(value = "other.xml", deprecated = true, roamingType = RoamingType.DISABLED))
class ErrorReportConfigurable implements PersistentStateComponent<ErrorReportConfigurable.State> {
public static final String SERVICE_NAME = "IntelliJ Platform — JetBrains Account";
static class State {
public String ITN_LOGIN;
public String ITN_PASSWORD_CRYPT;
}
public static ErrorReportConfigurable getInstance() {
return ServiceManager.getService(ErrorReportConfigurable.class);
}
@Nullable
@Override
public State getState() {
return new State();
}
@Override
public void loadState(State state) {
if (!StringUtil.isEmpty(state.ITN_LOGIN) || !StringUtil.isEmpty(state.ITN_PASSWORD_CRYPT)) {
PasswordSafe.getInstance().set(new CredentialAttributes(SERVICE_NAME, state.ITN_LOGIN), new Credentials(state.ITN_LOGIN, Base64.getDecoder().decode(state.ITN_PASSWORD_CRYPT)));
}
}
@Nullable
public static Credentials getCredentials() {
return PasswordSafe.getInstance().get(new CredentialAttributes(SERVICE_NAME));
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.diagnostic
import com.intellij.credentialStore.CredentialAttributes
import com.intellij.credentialStore.Credentials
import com.intellij.ide.passwordSafe.PasswordSafe
import com.intellij.openapi.components.*
import com.intellij.util.decodeBase64
@State(name = "ErrorReportConfigurable", storages = arrayOf(Storage(value = "other.xml", deprecated = true, roamingType = RoamingType.DISABLED)))
internal class ErrorReportConfigurable : PersistentStateComponent<OldState> {
override fun getState() = OldState()
override fun loadState(state: OldState) {
if (!state.ITN_LOGIN.isNullOrEmpty() || !state.ITN_PASSWORD_CRYPT.isNullOrEmpty()) {
PasswordSafe.getInstance().set(CredentialAttributes(SERVICE_NAME, state.ITN_LOGIN), Credentials(state.ITN_LOGIN, state.ITN_PASSWORD_CRYPT!!.decodeBase64()))
}
}
companion object {
@JvmStatic
val SERVICE_NAME = "IntelliJ Platform — JetBrains Account"
val instance: ErrorReportConfigurable
get() = ServiceManager.getService(ErrorReportConfigurable::class.java)
@JvmStatic
fun getCredentials() = PasswordSafe.getInstance().get(CredentialAttributes(SERVICE_NAME))
}
}
internal class OldState {
var ITN_LOGIN: String? = null
var ITN_PASSWORD_CRYPT: String? = null
}
@@ -1,204 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.diagnostic;
import com.intellij.CommonBundle;
import com.intellij.credentialStore.CredentialAttributesKt;
import com.intellij.credentialStore.Credentials;
import com.intellij.errorreport.bean.ErrorBean;
import com.intellij.errorreport.error.InternalEAPException;
import com.intellij.errorreport.error.NoSuchEAPUserException;
import com.intellij.errorreport.error.UpdateAvailableException;
import com.intellij.errorreport.itn.ITNProxy;
import com.intellij.ide.DataManager;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.idea.IdeaLogger;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.ErrorReportSubmitter;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diagnostic.SubmittedReportInfo;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Consumer;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
/**
* @author max
*/
public class ITNReporter extends ErrorReportSubmitter {
private static int previousExceptionThreadId = 0;
@Override
public String getReportActionText() {
return DiagnosticBundle.message("error.report.to.jetbrains.action");
}
@Override
public boolean submit(@NotNull IdeaLoggingEvent[] events,
String additionalInfo,
@NotNull Component parentComponent,
@NotNull Consumer<SubmittedReportInfo> consumer) {
ErrorBean errorBean = new ErrorBean(events[0].getThrowable(), IdeaLogger.ourLastActionId);
return doSubmit(events[0], parentComponent, consumer, errorBean, additionalInfo);
}
/**
* Used to enable error reporting even in release versions.
*/
public boolean showErrorInRelease(IdeaLoggingEvent event) {
return false;
}
private static boolean doSubmit(final IdeaLoggingEvent event,
final Component parentComponent,
final Consumer<SubmittedReportInfo> callback,
final ErrorBean errorBean,
final String description) {
Credentials credentials = ErrorReportConfigurable.getCredentials();
if (!CredentialAttributesKt.isFulfilled(credentials)) {
if (!new JetBrainsAccountDialog(parentComponent).showAndGet()) {
return false;
}
credentials = ErrorReportConfigurable.getCredentials();
}
errorBean.setDescription(description);
errorBean.setMessage(event.getMessage());
if (previousExceptionThreadId != 0) {
errorBean.setPreviousException(previousExceptionThreadId);
}
setPluginInfo(event, errorBean);
Object data = event.getData();
if (data instanceof AbstractMessage) {
errorBean.setAssigneeId(((AbstractMessage)data).getAssigneeId());
errorBean.setAttachments(((AbstractMessage)data).getIncludedAttachments());
}
String login = credentials == null ? null : credentials.getUserName();
String password = credentials == null ? null : credentials.getPasswordAsString();
if (StringUtil.isEmptyOrSpaces(login) && StringUtil.isEmptyOrSpaces(password)) {
login = "idea_anonymous";
password = "guest";
}
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parentComponent));
ITNProxy.sendError(project, login, password, errorBean, threadId -> {
updatePreviousThreadId(threadId);
String url = ITNProxy.getBrowseUrl(threadId);
String linkText = String.valueOf(threadId);
final SubmittedReportInfo reportInfo = new SubmittedReportInfo(url, linkText, SubmittedReportInfo.SubmissionStatus.NEW_ISSUE);
callback.consume(reportInfo);
ApplicationManager.getApplication().invokeLater(() -> {
StringBuilder text = new StringBuilder();
IdeErrorsDialog.appendSubmissionInformation(reportInfo, text);
text.append('.').append("<br/>").append(DiagnosticBundle.message("error.report.gratitude"));
String content = XmlStringUtil.wrapInHtml(text);
ReportMessages.GROUP
.createNotification(ReportMessages.ERROR_REPORT, content, NotificationType.INFORMATION, NotificationListener.URL_OPENING_LISTENER)
.setImportant(false)
.notify(project);
});
}, e -> {
Logger.getInstance(ITNReporter.class).info("reporting failed: " + e);
ApplicationManager.getApplication().invokeLater(() -> {
String msg;
if (e instanceof NoSuchEAPUserException) {
msg = DiagnosticBundle.message("error.report.authentication.failed");
}
else if (e instanceof InternalEAPException) {
msg = DiagnosticBundle.message("error.report.posting.failed", e.getMessage());
}
else {
msg = DiagnosticBundle.message("error.report.sending.failure");
}
if (e instanceof UpdateAvailableException) {
String message = DiagnosticBundle.message("error.report.new.eap.build.message", e.getMessage());
showMessageDialog(parentComponent, project, message, CommonBundle.getWarningTitle(), Messages.getWarningIcon());
callback.consume(new SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED));
}
else if (showYesNoDialog(parentComponent, project, msg, ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != Messages.YES) {
callback.consume(new SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED));
}
else {
if (e instanceof NoSuchEAPUserException) {
final JetBrainsAccountDialog dialog;
if (parentComponent.isShowing()) {
dialog = new JetBrainsAccountDialog(parentComponent);
}
else {
dialog = new JetBrainsAccountDialog(project);
}
dialog.show();
}
ApplicationManager.getApplication().invokeLater(() -> doSubmit(event, parentComponent, callback, errorBean, description));
}
});
});
return true;
}
public static void setPluginInfo(IdeaLoggingEvent event, ErrorBean errorBean) {
Throwable t = event.getThrowable();
if (t != null) {
final PluginId pluginId = IdeErrorsDialog.findPluginId(t);
if (pluginId != null) {
final IdeaPluginDescriptor ideaPluginDescriptor = PluginManager.getPlugin(pluginId);
if (ideaPluginDescriptor != null && (!ideaPluginDescriptor.isBundled() || ideaPluginDescriptor.allowBundledUpdate())) {
errorBean.setPluginName(ideaPluginDescriptor.getName());
errorBean.setPluginVersion(ideaPluginDescriptor.getVersion());
}
}
}
}
private static void updatePreviousThreadId(Integer threadId) {
previousExceptionThreadId = threadId;
}
private static void showMessageDialog(Component parentComponent, Project project, String message, String title, Icon icon) {
if (parentComponent.isShowing()) {
Messages.showMessageDialog(parentComponent, message, title, icon);
}
else {
Messages.showMessageDialog(project, message, title, icon);
}
}
@Messages.YesNoResult
private static int showYesNoDialog(Component parentComponent, Project project, String message, String title, Icon icon) {
if (parentComponent.isShowing()) {
return Messages.showYesNoDialog(parentComponent, message, title, icon);
}
else {
return Messages.showYesNoDialog(project, message, title, icon);
}
}
}
@@ -0,0 +1,170 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.diagnostic
import com.intellij.CommonBundle
import com.intellij.credentialStore.hasOnlyUserName
import com.intellij.errorreport.bean.ErrorBean
import com.intellij.errorreport.error.InternalEAPException
import com.intellij.errorreport.error.NoSuchEAPUserException
import com.intellij.errorreport.error.UpdateAvailableException
import com.intellij.errorreport.itn.ITNProxy
import com.intellij.ide.DataManager
import com.intellij.ide.plugins.PluginManager
import com.intellij.idea.IdeaLogger
import com.intellij.notification.NotificationListener
import com.intellij.notification.NotificationType
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.ErrorReportSubmitter
import com.intellij.openapi.diagnostic.IdeaLoggingEvent
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.diagnostic.SubmittedReportInfo
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.util.Consumer
import com.intellij.xml.util.XmlStringUtil
import java.awt.Component
import javax.swing.Icon
private var previousExceptionThreadId = 0
open class ITNReporter : ErrorReportSubmitter() {
override fun getReportActionText(): String = DiagnosticBundle.message("error.report.to.jetbrains.action")
override fun submit(events: Array<IdeaLoggingEvent>,
additionalInfo: String?,
parentComponent: Component,
consumer: Consumer<SubmittedReportInfo>): Boolean {
return submit(events.get(0), parentComponent, consumer, ErrorBean(events.get(0).throwable, IdeaLogger.ourLastActionId), additionalInfo)
}
/**
* Used to enable error reporting even in release versions.
*/
open fun showErrorInRelease(event: IdeaLoggingEvent) = false
}
fun setPluginInfo(event: IdeaLoggingEvent, errorBean: ErrorBean) {
val t = event.throwable
if (t != null) {
val pluginId = IdeErrorsDialog.findPluginId(t)
if (pluginId != null) {
val ideaPluginDescriptor = PluginManager.getPlugin(pluginId)
if (ideaPluginDescriptor != null && (!ideaPluginDescriptor.isBundled || ideaPluginDescriptor.allowBundledUpdate())) {
errorBean.pluginName = ideaPluginDescriptor.name
errorBean.pluginVersion = ideaPluginDescriptor.version
}
}
}
}
private fun updatePreviousThreadId(threadId: Int?) {
previousExceptionThreadId = threadId!!
}
private fun showMessageDialog(parentComponent: Component, project: Project?, message: String, title: String, icon: Icon) {
if (parentComponent.isShowing) {
Messages.showMessageDialog(parentComponent, message, title, icon)
}
else {
Messages.showMessageDialog(project, message, title, icon)
}
}
@Messages.YesNoResult
private fun showYesNoDialog(parentComponent: Component, project: Project?, message: String, title: String, icon: Icon): Int {
if (parentComponent.isShowing) {
return Messages.showYesNoDialog(parentComponent, message, title, icon)
}
else {
return Messages.showYesNoDialog(project, message, title, icon)
}
}
private fun submit(event: IdeaLoggingEvent, parentComponent: Component, callback: Consumer<SubmittedReportInfo>, errorBean: ErrorBean, description: String?): Boolean {
var credentials = ErrorReportConfigurable.getCredentials()
// ask password only if user name was specified
if (credentials.hasOnlyUserName()) {
if (!showJetBrainsAccountDialog(parentComponent).showAndGet()) {
return false
}
credentials = ErrorReportConfigurable.getCredentials()
}
errorBean.description = description
errorBean.message = event.message
if (previousExceptionThreadId != 0) {
errorBean.previousException = previousExceptionThreadId
}
setPluginInfo(event, errorBean)
val data = event.data
if (data is AbstractMessage) {
errorBean.assigneeId = data.assigneeId
errorBean.attachments = data.includedAttachments
}
var login = credentials?.userName
var password = credentials?.getPasswordAsString()
if (login.isNullOrBlank() && password.isNullOrBlank()) {
login = "idea_anonymous"
password = "guest"
}
val project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parentComponent))
ITNProxy.sendError(project, login, password, errorBean, { threadId ->
updatePreviousThreadId(threadId)
val url = ITNProxy.getBrowseUrl(threadId!!)
val linkText = threadId.toString()
val reportInfo = SubmittedReportInfo(url, linkText, SubmittedReportInfo.SubmissionStatus.NEW_ISSUE)
callback.consume(reportInfo)
ApplicationManager.getApplication().invokeLater {
val text = StringBuilder()
IdeErrorsDialog.appendSubmissionInformation(reportInfo, text)
text.append('.').append("<br/>").append(DiagnosticBundle.message("error.report.gratitude"))
val content = XmlStringUtil.wrapInHtml(text)
ReportMessages.GROUP.createNotification(ReportMessages.ERROR_REPORT, content, NotificationType.INFORMATION,
NotificationListener.URL_OPENING_LISTENER).setImportant(false).notify(project)
}
}) { e ->
Logger.getInstance(ITNReporter::class.java).info("reporting failed: " + e)
ApplicationManager.getApplication().invokeLater {
val msg = when (e) {
is NoSuchEAPUserException -> DiagnosticBundle.message("error.report.authentication.failed")
is InternalEAPException -> DiagnosticBundle.message("error.report.posting.failed", e.message)
else -> DiagnosticBundle.message("error.report.sending.failure")
}
if (e is UpdateAvailableException) {
val message = DiagnosticBundle.message("error.report.new.eap.build.message", e.message)
showMessageDialog(parentComponent, project, message, CommonBundle.getWarningTitle(), Messages.getWarningIcon())
callback.consume(SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED))
}
else if (showYesNoDialog(parentComponent, project, msg, ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != Messages.YES) {
callback.consume(SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED))
}
else if (e is NoSuchEAPUserException) {
showJetBrainsAccountDialog(parentComponent, project).show()
}
ApplicationManager.getApplication().invokeLater { submit(event, parentComponent, callback, errorBean, description) }
}
}
return true
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -347,7 +347,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
new JetBrainsAccountDialog(getRootPane()).show();
JetBrainsAccountDialogKt.showJetBrainsAccountDialog(getRootPane()).show();
updateCredentialsPane(getSelectedMessage());
}
}
@@ -1,111 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.diagnostic;
import com.intellij.credentialStore.CredentialAttributes;
import com.intellij.credentialStore.Credentials;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.passwordSafe.PasswordSafe;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ClickListener;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
public class JetBrainsAccountDialog extends DialogWrapper {
private JTextField myItnLoginTextField;
private JPasswordField myPasswordText;
private JCheckBox myRememberCheckBox;
public JetBrainsAccountDialog(Component parent) throws HeadlessException {
super(parent, false);
init();
}
public JetBrainsAccountDialog(Project project) throws HeadlessException {
super(project, false);
init();
}
protected JPanel myMainPanel;
protected JLabel mySendingSettingsLabel;
private JLabel myCreateAccountLabel;
@Override
protected String getDimensionServiceKey() {
return "#com.intellij.diagnostic.AbstractSendErrorDialog";
}
@Override
public JComponent getPreferredFocusedComponent() {
return myItnLoginTextField;
}
@Override
protected void init() {
setTitle(ReportMessages.ERROR_REPORT);
getContentPane().add(myMainPanel);
new ClickListener() {
@Override
public boolean onClick(@NotNull MouseEvent e, int clickCount) {
HttpConfigurable.editConfigurable(myMainPanel);
return true;
}
}.installOn(mySendingSettingsLabel);
mySendingSettingsLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
Credentials credentials = ErrorReportConfigurable.getCredentials();
String userName = credentials == null ? null : credentials.getUserName();
myItnLoginTextField.setText(userName);
String password = credentials == null ? null : credentials.getPasswordAsString();
myPasswordText.setText(password);
// if no user name - never stored and so, defaults to remember. if user name set, but no password, so, previously was stored without password
myRememberCheckBox.setSelected(StringUtil.isEmpty(userName) || !StringUtil.isEmpty(password));
new ClickListener() {
@Override
public boolean onClick(@NotNull MouseEvent e, int clickCount) {
BrowserUtil.browse("http://account.jetbrains.com");
return true;
}
}.installOn(myCreateAccountLabel);
myCreateAccountLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
super.init();
}
@Override
protected void doOKAction() {
String userName = myItnLoginTextField.getText();
if (!StringUtil.isEmpty(userName)) {
PasswordSafe.getInstance().set(new CredentialAttributes(ErrorReportConfigurable.SERVICE_NAME, userName),
new Credentials(userName, myRememberCheckBox.isSelected() ? myPasswordText.getPassword() : null));
}
super.doOKAction();
}
@Override
protected JComponent createCenterPanel() {
return myMainPanel;
}
}
@@ -0,0 +1,72 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.diagnostic
import com.intellij.CommonBundle
import com.intellij.credentialStore.CredentialAttributes
import com.intellij.credentialStore.Credentials
import com.intellij.ide.passwordSafe.PasswordSafe
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogBuilder
import com.intellij.openapi.ui.dialog
import com.intellij.openapi.ui.ex.MultiLineLabel
import com.intellij.ui.components.JBCheckBox
import com.intellij.ui.layout.*
import com.intellij.ui.layout.CCFlags.*
import com.intellij.ui.layout.LCFlags.*
import com.intellij.util.net.HttpConfigurable
import java.awt.Component
import javax.swing.JPasswordField
import javax.swing.JTextField
@JvmOverloads
fun showJetBrainsAccountDialog(parent: Component, project: Project? = null): DialogBuilder {
val credentials = ErrorReportConfigurable.getCredentials()
val userField = JTextField(credentials?.userName)
val passwordField = JPasswordField(credentials?.password?.toString())
// if no user name - never stored and so, defaults to remember. if user name set, but no password, so, previously was stored without password
val rememberCheckBox = JBCheckBox(CommonBundle.message("checkbox.remember.password"), credentials?.userName == null || !credentials?.password.isNullOrEmpty())
val panel = panel(fillX) {
MultiLineLabel(DiagnosticBundle.message("diagnostic.error.report.description"))(span, wrap)
link(DiagnosticBundle.message("diagnostic.error.report.proxy.setup"), span, wrap) {
HttpConfigurable.editConfigurable(this)
}
label("Username:")
userField(grow, wrap)
label("Password:")
passwordField(grow, wrap)
rememberCheckBox(span, wrap)
link("Create or manage your JetBrains Account", "https://account.jetbrains.com", span, wrap)
}
return dialog(
title = DiagnosticBundle.message("error.report.title"),
centerPanel = panel,
preferedFocusComponent = if (credentials?.userName == null) userField else passwordField,
project = project,
parent = if (parent.isShowing) parent else null) {
val userName = userField.text
if (!userName.isNullOrBlank()) {
PasswordSafe.getInstance().set(CredentialAttributes(ErrorReportConfigurable.SERVICE_NAME, userName), Credentials(userName, if (rememberCheckBox.isSelected) passwordField.password else null))
}
}
}
@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.diagnostic.JetBrainsAccountDialog">
<grid id="92fcd" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="69" y="123" width="372" height="302"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="46178" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="2" left="4" bottom="0" right="4"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
</clientProperties>
<border type="none"/>
<children>
<component id="4f69e" class="javax.swing.JCheckBox" binding="myRememberCheckBox">
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.login.remember.password.checkbox"/>
</properties>
</component>
<component id="2c912" class="javax.swing.JLabel" binding="myCreateAccountLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&lt;html&gt;&lt;a href=&quot;#&quot;&gt;Create or manage your JetBrains Account&lt;/a&gt;&lt;/html&gt;"/>
</properties>
</component>
<component id="fbdcc" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="b3002"/>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.login.password"/>
</properties>
</component>
<component id="87071" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="e3ed"/>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.login.name"/>
</properties>
</component>
<component id="e3ed" class="javax.swing.JTextField" binding="myItnLoginTextField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="b3002" class="javax.swing.JPasswordField" binding="myPasswordText">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
</children>
</grid>
<component id="115f0" class="javax.swing.JLabel" binding="mySendingSettingsLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.proxy.setup"/>
</properties>
</component>
<component id="cd549" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.description"/>
</properties>
</component>
</children>
</grid>
</form>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -291,13 +291,8 @@ class ConfigurableEditor extends AbstractEditor implements AnActionListener, AWT
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
content.add(BorderLayout.CENTER, panel);
panel.add(Box.createVerticalStrut(10));
for (final Configurable current : composite.getConfigurables()) {
LinkLabel label = new LinkLabel(current.getDisplayName(), null) {
@Override
public void doClick() {
openLink(current);
}
};
for (Configurable current : composite.getConfigurables()) {
LinkLabel label = LinkLabel.create(current.getDisplayName(), () -> openLink(current));
label.setBorder(BorderFactory.createEmptyBorder(1, 17, 3, 1));
panel.add(label);
}
@@ -0,0 +1,65 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ui
import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase
import com.intellij.util.ui.SwingHelper
import com.intellij.util.ui.UIUtil
import java.awt.Color
import java.awt.Font
import java.util.regex.Pattern
import javax.swing.JEditorPane
private val HREF_PATTERN = Pattern.compile("<a(?:\\s+href\\s*=\\s*[\"']([^\"']*)[\"'])?\\s*>([^<]*)</a>")
private val LINK_TEXT_ATTRIBUTES = SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, JBColor.blue)
private val SMALL_TEXT_ATTRIBUTES = SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, null)
fun noteComponent(note: String): SimpleColoredComponent {
val noteComponent = SimpleColoredComponent()
val matcher = HREF_PATTERN.matcher(note)
var prev = 0
if (matcher.find()) {
do {
if (matcher.start() != prev) {
noteComponent.append(note.substring(prev, matcher.start()), SMALL_TEXT_ATTRIBUTES)
}
noteComponent.append(matcher.group(2), LINK_TEXT_ATTRIBUTES, SimpleColoredComponent.BrowserLauncherTag(matcher.group(1)))
prev = matcher.end()
}
while (matcher.find())
LinkMouseListenerBase.installSingleTagOn(noteComponent)
}
if (prev < note.length) {
noteComponent.append(note.substring(prev), SMALL_TEXT_ATTRIBUTES)
}
return noteComponent
}
@JvmOverloads
fun htmlComponent(text: String = "", font: Font = UIUtil.getLabelFont(), background: Color? = null, foreground: Color? = null, lineWrap: Boolean = false): JEditorPane {
val pane = SwingHelper.createHtmlViewer(lineWrap, font, background, foreground)
if (!text.isNullOrEmpty()) {
pane.text = "<html><head>${UIUtil.getCssFontDeclaration(font, UIUtil.getLabelForeground(), null, null)}</head><body>$text</body></html>"
}
pane.border = null
pane.disabledTextColor = UIUtil.getLabelDisabledForeground()
pane.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE)
return pane
}
@@ -0,0 +1,63 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ui.layout
// http://www.migcalendar.com/miglayout/mavensite/docs/cheatsheet.pdf
enum class CFlags {
}
enum class LCFlags {
/**
* Puts the layout in a flow-only mode.
* All components in the flow direction will be put in the same cell and will thus not be aligned with component in other rows/columns.
* For normal horizontal flow this is the same as to say that all component will be put in the first and only column.
*/
noGrid,
/**
* Puts the layout in vertical flow mode. This means that the next cell is normally below and the next component will be put there instead of to the right. Default is horizontal flow.
*/
flowY,
/**
* Claims all available space in the container for the columns and/or rows.
* At least one component need to have a "grow" constraint for it to fill the container.
* The space will be divided equal, though honoring "growPriority".
* If no columns/rows has "grow" set the grow weight of the components in the rows/columns will migrate to that row/column.
*/
fill, fillX, fillY,
lcWrap,
debug
}
enum class CCFlags {
/**
* Wrap to the next line/column **after** the component that this constraint belongs to.
*/
wrap,
/**
* Span cells in both x and y.
*/
span, spanX, spanY,
split,
grow, push, pushY, pushX, right, skip
}
@@ -16,58 +16,20 @@
package com.intellij.ui.layout
import com.intellij.BundleBase
import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase
import com.intellij.ui.*
import com.intellij.ide.BrowserUtil
import com.intellij.ui.IdeBorderFactory
import com.intellij.ui.components.JBLabel
import com.intellij.util.ui.SwingHelper
import com.intellij.ui.components.labels.LinkLabel
import com.intellij.util.ui.UIUtil
import com.intellij.util.ui.UIUtil.getCssFontDeclaration
import com.intellij.util.ui.UIUtil.getLabelForeground
import net.miginfocom.layout.*
import net.miginfocom.swing.MigLayout
import java.awt.*
import java.awt.BorderLayout
import java.awt.Component
import java.awt.Font
import java.awt.LayoutManager
import java.awt.event.ActionEvent
import java.util.regex.Pattern
import javax.swing.*
// http://www.migcalendar.com/miglayout/mavensite/docs/cheatsheet.pdf
enum class LCFlags {
/**
* Puts the layout in a flow-only mode.
* All components in the flow direction will be put in the same cell and will thus not be aligned with component in other rows/columns.
* For normal horizontal flow this is the same as to say that all component will be put in the first and only column.
*/
noGrid,
/**
* Puts the layout in vertical flow mode. This means that the next cell is normally below and the next component will be put there instead of to the right. Default is horizontal flow.
*/
flowY,
/**
* Claims all available space in the container for the columns and/or rows.
* At least one component need to have a "grow" constraint for it to fill the container.
* The space will be divided equal, though honoring "growPriority".
* If no columns/rows has "grow" set the grow weight of the components in the rows/columns will migrate to that row/column.
*/
fill, fillX, fillY
}
enum class CCFlags {
/**
* Wrap to the next line/column **after** the component that this constraint belongs to.
*/
wrap,
/**
* Span cells in both x and y.
*/
span,
grow, push, pushY, pushX, right, skip
}
inline fun panel(vararg layoutConstraints: LCFlags, init: Panel.() -> Unit): JPanel {
val panel = Panel(MigLayout(c().apply(layoutConstraints)))
panel.init()
@@ -88,7 +50,15 @@ fun JPanel.titledPanel(title: String, wrappedComponent: Component, vararg constr
add(panel, *constraints)
}
fun JPanel.label(text: String, vararg constraints: CCFlags, componentStyle: UIUtil.ComponentStyle? = null, fontColor: UIUtil.FontColor? = null, bold: Boolean = false, gapLeft: Int = 0, gapBottom: Int = 0, gapAfter: Int = 0) {
fun JPanel.label(text: String,
vararg constraints: CCFlags,
componentStyle: UIUtil.ComponentStyle? = null,
fontColor: UIUtil.FontColor? = null,
bold: Boolean = false,
gapLeft: Int = 0,
gapBottom: Int = 0,
gapAfter: Int = 0,
split: Int = -1) {
val finalText = BundleBase.replaceMnemonicAmpersand(text)
val label = if (componentStyle == null && fontColor == null) {
JLabel(finalText)
@@ -118,9 +88,20 @@ fun JPanel.label(text: String, vararg constraints: CCFlags, componentStyle: UIUt
if (gapBottom != 0) {
cc().vertical.gapAfter = gapToBoundSize(gapBottom, false)
}
if (split != -1) {
cc().split = split
}
add(label, _cc)
}
fun JPanel.link(text: String, vararg constraints: CCFlags, action: () -> Unit) {
add(LinkLabel.create(text, action), constraints.create())
}
fun JPanel.link(text: String, url: String, vararg constraints: CCFlags) {
add(LinkLabel.create(text, { BrowserUtil.browse(url) }), constraints.create())
}
private fun gapToBoundSize(value: Int, isHorizontal: Boolean): BoundSize {
val unitValue = UnitValue(value.toFloat(), "", isHorizontal, UnitValue.STATIC, null)
return BoundSize(unitValue, unitValue, null, false, null)
@@ -194,6 +175,10 @@ fun LC.apply(flags: Array<out LCFlags>): LC {
LCFlags.fill -> fill()
LCFlags.fillX -> isFillX = true
LCFlags.fillY -> isFillY = true
LCFlags.lcWrap -> wrapAfter = 0
LCFlags.debug -> debug()
}
}
return this
@@ -211,49 +196,13 @@ fun CC.apply(flags: Array<out CCFlags>): CC {
CCFlags.pushY -> pushY()
CCFlags.span -> span()
CCFlags.spanX -> spanX()
CCFlags.spanY -> spanY()
CCFlags.split -> split()
CCFlags.skip -> skip()
}
}
return this
}
private val HREF_PATTERN = Pattern.compile("<a(?:\\s+href\\s*=\\s*[\"']([^\"']*)[\"'])?\\s*>([^<]*)</a>")
private val LINK_TEXT_ATTRIBUTES = SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, JBColor.blue)
private val SMALL_TEXT_ATTRIBUTES = SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, null)
fun noteComponent(note: String): SimpleColoredComponent {
val noteComponent = SimpleColoredComponent()
val matcher = HREF_PATTERN.matcher(note)
var prev = 0
if (matcher.find()) {
do {
if (matcher.start() != prev) {
noteComponent.append(note.substring(prev, matcher.start()), SMALL_TEXT_ATTRIBUTES)
}
noteComponent.append(matcher.group(2), LINK_TEXT_ATTRIBUTES, SimpleColoredComponent.BrowserLauncherTag(matcher.group(1)))
prev = matcher.end()
}
while (matcher.find())
LinkMouseListenerBase.installSingleTagOn(noteComponent)
}
if (prev < note.length) {
noteComponent.append(note.substring(prev), SMALL_TEXT_ATTRIBUTES)
}
return noteComponent
}
@JvmOverloads
fun htmlComponent(text: String = "", font: Font = UIUtil.getLabelFont(), background: Color? = null, foreground: Color? = null, lineWrap: Boolean = false): JEditorPane {
val pane = SwingHelper.createHtmlViewer(lineWrap, font, background, foreground)
if (!text.isNullOrEmpty()) {
pane.text = "<html><head>${getCssFontDeclaration(font, getLabelForeground(), null, null)}</head><body>$text</body></html>"
}
pane.border = null
pane.disabledTextColor = UIUtil.getLabelDisabledForeground()
pane.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE)
return pane
}
@@ -9,14 +9,10 @@ diagnostic.out.of.memory.currentValue.unknown=Unknown
diagnostic.out.of.memory.continue=Continue
diagnostic.out.of.memory.dump=Memory Dump
diagnostic.error.report.send=&Send
diagnostic.error.report.description=<html>If you would like to get notified when the exceptions you submit are fixed,<br>please fill in your JetBrains Account login and password.</html>
diagnostic.error.report.proxy.setup=<html><a href="#">Set up HTTP proxy settings</a></html>
diagnostic.error.report.login.group=JetBrains Account
diagnostic.error.report.login.remember.password.checkbox=&Remember password
diagnostic.error.report.description=If you would like to get notified when the exceptions you submit are fixed,\nplease fill in your JetBrains Account login and password.
diagnostic.error.report.proxy.setup=Set up HTTP proxy settings
diagnostic.error.report.login.name=&Username:
diagnostic.error.report.login.password=&Password:
diagnostic.error.report.prompt=Error description (optional):
diagnostic.error.report.use.jetbrains.account.button.label=&Use JetBrains Account...
diagnostic.error.report.submit.error.anonymously=<html>Submit report anonymously or use <a>JetBrains Account...</a></html>
diagnostic.error.report.submit.report.as=<html>Submit report as <a>{0}</a></html>
diagnostic.error.report.additional.info.label=&Additional information (steps to reproduce, what were you doing when the exception occurred):
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@ import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.ui.components.labels.LinkLabel;
import com.intellij.ui.components.labels.LinkListener;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -91,13 +90,10 @@ class VcsUpdateInfoScopeFilterConfigurable implements Configurable, NamedScopesH
panel.add(myCheckbox);
panel.add(myComboBox);
panel.add(Box.createHorizontalStrut(UIUtil.DEFAULT_HGAP));
panel.add(new LinkLabel("Manage Scopes", null, new LinkListener() {
@Override
public void linkSelected(LinkLabel aSource, Object aLinkData) {
Settings settings = Settings.KEY.getData(DataManager.getInstance().getDataContext(panel));
if (settings != null) {
settings.select(settings.find(ScopeChooserConfigurable.PROJECT_SCOPES));
}
panel.add(LinkLabel.create("Manage Scopes", () -> {
Settings settings = Settings.KEY.getData(DataManager.getInstance().getDataContext(panel));
if (settings != null) {
settings.select(settings.find(ScopeChooserConfigurable.PROJECT_SCOPES));
}
}));
return panel;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.components.labels.LinkLabel;
import com.intellij.ui.components.labels.LinkListener;
import com.intellij.util.ui.UIUtil;
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
@@ -33,13 +32,6 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created with IntelliJ IDEA.
* User: zajac
* Date: 4/4/12
* Time: 5:51 PM
* To change this template use File | Settings | File Templates.
*/
public class BreakpointEditor {
public JPanel getMainPanel() {
return myMainPanel;
@@ -49,12 +41,9 @@ public class BreakpointEditor {
AnAction action = ActionManager.getInstance().getAction(XDebuggerActions.VIEW_BREAKPOINTS);
String shortcutText = action != null ? KeymapUtil.getFirstKeyboardShortcutText(action) : null;
String text = shortcutText != null ? "More (" + shortcutText + ")" : "More";
myShowMoreOptionsLink = new LinkLabel(text, null, new LinkListener() {
@Override
public void linkSelected(LinkLabel aSource, Object aLinkData) {
if (myDelegate != null) {
myDelegate.more();
}
myShowMoreOptionsLink = LinkLabel.create(text, () -> {
if (myDelegate != null) {
myDelegate.more();
}
});
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.labels.LinkLabel;
import com.intellij.ui.components.labels.LinkListener;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -76,12 +75,7 @@ public class GitCrlfDialog extends DialogWrapper {
"<html>Fix and Commit: <code>git config --global core.autocrlf " + RECOMMENDED_VALUE + "</code> will be called,<br/>" +
"Commit as Is: the config value won't be set.</html>", UIUtil.ComponentStyle.SMALL);
JLabel readMore = new LinkLabel("Read more", null, new LinkListener() {
@Override
public void linkSelected(LinkLabel aSource, Object aLinkData) {
BrowserUtil.browse("https://help.github.com/articles/dealing-with-line-endings");
}
});
JLabel readMore = LinkLabel.create("Read more", () -> BrowserUtil.browse("https://help.github.com/articles/dealing-with-line-endings"));
JLabel icon = new JLabel(UIUtil.getWarningIcon(), SwingConstants.LEFT);
myDontWarn = new JBCheckBox("Don't warn again");
+2 -1
View File
@@ -23,7 +23,9 @@ import com.intellij.openapi.ui.dialog
import com.intellij.ui.DocumentAdapter
import com.intellij.ui.layout.*
import com.intellij.ui.layout.CCFlags.*
import com.intellij.ui.layout.CCFlags.wrap
import com.intellij.ui.layout.LCFlags.*
import com.intellij.ui.noteComponent
import com.intellij.util.PathUtilRt
import com.intellij.util.nullize
import com.intellij.util.trimMiddle
@@ -67,7 +69,6 @@ fun showAuthenticationForm(credentials: Credentials?, uri: String, host: String?
val authenticationForm = dialog(
title = "Settings Repository",
resizable = false,
centerPanel = centerPanel,
preferedFocusComponent = if (userField.parent == null) passwordField else userField,
okActionEnabled = false)