/*
* 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.popup;
import com.intellij.ide.IdeTooltipManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.BalloonBuilder;
import com.intellij.openapi.ui.popup.JBPopupAdapter;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.BalloonImpl;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class BalloonPopupBuilderImpl implements BalloonBuilder {
@Nullable private final Map<Disposable, List<Balloon>> myStorage;
@Nullable private Disposable myAnchor;
private final JComponent myContent;
private Color myBorder = IdeTooltipManager.getInstance().getBorderColor(true);
@Nullable private Insets myBorderInsets = null;
private Color myFill = MessageType.INFO.getPopupBackground();
private boolean myHideOnMouseOutside = true;
private boolean myHideOnKeyOutside = true;
private long myFadeoutTime = -1;
private boolean myShowCallout = true;
private boolean myCloseButtonEnabled = false;
private boolean myHideOnFrameResize = true;
private boolean myHideOnLinkClick = false;
private ActionListener myClickHandler;
private boolean myCloseOnClick;
private int myAnimationCycle = 500;
private int myCalloutShift;
private int myPositionChangeXShift;
private int myPositionChangeYShift;
private boolean myHideOnAction = true;
private boolean myHideOnCloseClick = true;
private boolean myDialogMode;
private String myTitle;
private Insets myContentInsets = JBUI.insets(2);
private boolean myShadow = UIUtil.isUnderDarcula();
private boolean mySmallVariant = false;
private Balloon.Layer myLayer;
private boolean myBlockClicks = false;
private boolean myRequestFocus = false;
public BalloonPopupBuilderImpl(@Nullable Map<Disposable, List<Balloon>> storage, @NotNull final JComponent content) {
myStorage = storage;
myContent = content;
}
@NotNull
@Override
public BalloonBuilder setHideOnAction(boolean hideOnAction) {
myHideOnAction = hideOnAction;
return this;
}
@NotNull
@Override
public BalloonBuilder setDialogMode(boolean dialogMode) {
myDialogMode = dialogMode;
return this;
}
@NotNull
@Override
public BalloonBuilder setBorderColor(@NotNull final Color color) {
myBorder = color;
return this;
}
@NotNull
@Override
public BalloonBuilder setBorderInsets(@Nullable Insets insets) {
myBorderInsets = insets;
return this;
}
@NotNull
@Override
public BalloonBuilder setFillColor(@NotNull final Color color) {
myFill = color;
return this;
}
@NotNull
@Override
public BalloonBuilder setHideOnClickOutside(final boolean hide) {
myHideOnMouseOutside = hide;
return this;
}
@NotNull
@Override
public BalloonBuilder setHideOnKeyOutside(final boolean hide) {
myHideOnKeyOutside = hide;
return this;
}
@NotNull
@Override
public BalloonBuilder setShowCallout(final boolean show) {
myShowCallout = show;
return this;
}
@NotNull
@Override
public BalloonBuilder setFadeoutTime(long fadeoutTime) {
myFadeoutTime = fadeoutTime;
return this;
}
@NotNull
@Override
public BalloonBuilder setBlockClicksThroughBalloon(boolean block) {
myBlockClicks = block;
return this;
}
@NotNull
@Override
public BalloonBuilder setRequestFocus(boolean requestFocus) {
myRequestFocus = requestFocus;
return this;
}
@Override
public BalloonBuilder setHideOnCloseClick(boolean hideOnCloseClick) {
myHideOnCloseClick = hideOnCloseClick;
return this;
}
@NotNull
@Override
public BalloonBuilder setAnimationCycle(int time) {
myAnimationCycle = time;
return this;
}
@NotNull
@Override
public BalloonBuilder setHideOnFrameResize(boolean hide) {
myHideOnFrameResize = hide;
return this;
}
@NotNull
@Override
public BalloonBuilder setHideOnLinkClick(boolean hide) {
myHideOnLinkClick = hide;
return this;
}
@NotNull
@Override
public BalloonBuilder setPositionChangeXShift(int positionChangeXShift) {
myPositionChangeXShift = positionChangeXShift;
return this;
}
@NotNull
@Override
public BalloonBuilder setPositionChangeYShift(int positionChangeYShift) {
myPositionChangeYShift = positionChangeYShift;
return this;
}
@NotNull
@Override
public BalloonBuilder setCloseButtonEnabled(boolean enabled) {
myCloseButtonEnabled = enabled;
return this;
}
@NotNull
@Override
public BalloonBuilder setClickHandler(ActionListener listener, boolean closeOnClick) {
myClickHandler = listener;
myCloseOnClick = closeOnClick;
return this;
}
@NotNull
@Override
public BalloonBuilder setCalloutShift(int length) {
myCalloutShift = length;
return this;
}
@NotNull
@Override
public BalloonBuilder setTitle(@Nullable String title) {
myTitle = title;
return this;
}
@NotNull
@Override
public BalloonBuilder setContentInsets(Insets insets) {
myContentInsets = insets;
return this;
}
@NotNull
@Override
public BalloonBuilder setShadow(boolean shadow) {
myShadow = shadow;
return this;
}
@NotNull
@Override
public BalloonBuilder setSmallVariant(boolean smallVariant) {
mySmallVariant = smallVariant;
return this;
}
@NotNull
@Override
public BalloonBuilder setLayer(Balloon.Layer layer) {
myLayer = layer;
return this;
}
@NotNull
@Override
public BalloonBuilder setDisposable(@NotNull Disposable anchor) {
myAnchor = anchor;
return this;
}
@NotNull
@Override
public Balloon createBalloon() {
final BalloonImpl result = new BalloonImpl(
myContent, myBorder, myBorderInsets, myFill, myHideOnMouseOutside, myHideOnKeyOutside, myHideOnAction, myHideOnCloseClick,
myShowCallout, myCloseButtonEnabled, myFadeoutTime, myHideOnFrameResize, myHideOnLinkClick, myClickHandler, myCloseOnClick,
myAnimationCycle, myCalloutShift, myPositionChangeXShift, myPositionChangeYShift, myDialogMode, myTitle, myContentInsets, myShadow,
mySmallVariant, myBlockClicks, myLayer, myRequestFocus);
if (myStorage != null && myAnchor != null) {
List<Balloon> balloons = myStorage.get(myAnchor);
if (balloons == null) {
myStorage.put(myAnchor, balloons = new ArrayList<>());
Disposer.register(myAnchor, new Disposable() {
@Override
public void dispose() {
List<Balloon> toDispose = myStorage.remove(myAnchor);
if (toDispose != null) {
for (Balloon balloon : toDispose) {
if (!balloon.isDisposed()) {
Disposer.dispose(balloon);
}
}
}
}
});
}
balloons.add(result);
result.addListener(new JBPopupAdapter() {
@Override
public void onClosed(LightweightWindowEvent event) {
if (!result.isDisposed()) {
Disposer.dispose(result);
}
}
});
}
return result;
}
}