Browse Source

Added option to use ToolTipContext via client properties. If non is set and the style of the tooltip is set to BALLOON then the a default context is used. The default style is PLAIN_BALLOON which behaves as the previous BALLOON style.

pull/97/head
weisj 5 years ago
parent
commit
494bd7dcdc
  1. 171
      core/src/main/java/com/github/weisj/darklaf/components/tooltip/DarkToolTip.java
  2. 279
      core/src/main/java/com/github/weisj/darklaf/components/tooltip/ToolTipContext.java
  3. 36
      core/src/main/java/com/github/weisj/darklaf/components/tooltip/ToolTipListener.java
  4. 1
      core/src/main/java/com/github/weisj/darklaf/components/tooltip/ToolTipStyle.java
  5. 9
      core/src/main/java/com/github/weisj/darklaf/ui/BasicTransferable.java
  6. 6
      core/src/main/java/com/github/weisj/darklaf/ui/DarkPopupFactory.java
  7. 19
      core/src/main/java/com/github/weisj/darklaf/ui/tooltip/DarkTooltipBorder.java
  8. 65
      core/src/main/java/com/github/weisj/darklaf/ui/tooltip/DarkTooltipUI.java
  9. 179
      core/src/main/java/com/github/weisj/darklaf/ui/tooltip/ToolTipUtil.java
  10. 1
      core/src/test/java/ui/dialog/DialogDemo.java
  11. 10
      core/src/test/java/ui/toolTip/ToolTipDemo.java

171
core/src/main/java/com/github/weisj/darklaf/components/tooltip/DarkToolTip.java

@ -1,171 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* 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:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* 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.github.weisj.darklaf.components.tooltip;
import com.github.weisj.darklaf.ui.tooltip.DarkTooltipBorder;
import com.github.weisj.darklaf.ui.tooltip.DarkTooltipUI;
import com.github.weisj.darklaf.util.Alignment;
import com.github.weisj.darklaf.util.Animator;
import com.github.weisj.darklaf.util.GraphicsContext;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Objects;
public class DarkToolTip extends JToolTip implements PropertyChangeListener {
private static final AlphaComposite COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
private static final float MAX_ALPHA = 1.0f;
private final Animator fadeAnimator;
private float alpha = 0;
public DarkToolTip(final Alignment alignment) {
setAlignment(alignment);
setOpaque(false);
fadeAnimator = new FadeInAnimator();
addPropertyChangeListener(this);
}
@Override
public void addNotify() {
alpha = 0;
setVisible(true);
notifyToolTipListeners(ToolTipEvent.SHOWN);
fadeAnimator.reset();
fadeAnimator.resume();
super.addNotify();
}
public void setAlignment(final Alignment alignment) {
putClientProperty(DarkTooltipUI.KEY_POINTER_LOCATION, alignment);
}
public void notifyToolTipListeners(final ToolTipEvent event) {
for (ToolTipListener listener : listenerList.getListeners(ToolTipListener.class)) {
if (listener != null) {
switch (event) {
case TEXT:
listener.textChanged(this);
break;
case SHOWN:
listener.toolTipShown(this);
break;
case HIDDEN:
listener.toolTipHidden(this);
break;
}
}
}
}
public void setInsets(final Insets insets) {
putClientProperty(DarkTooltipUI.KEY_INSETS, insets);
}
public void addToolTipListener(final ToolTipListener listener) {
listenerList.add(ToolTipListener.class, listener);
}
public void removeToolTipListener(final ToolTipListener listener) {
listenerList.remove(ToolTipListener.class, listener);
}
@Override
public void paint(final Graphics g) {
if (alpha == 0) return;
GraphicsContext config = new GraphicsContext(g);
if (alpha != MAX_ALPHA) {
((Graphics2D) g).setComposite(COMPOSITE.derive(alpha));
}
super.paint(g);
config.restore();
}
@Override
public void setBorder(final Border border) {
if (!(border instanceof DarkTooltipBorder)) return;
super.setBorder(border);
}
@Override
public void removeNotify() {
super.removeNotify();
notifyToolTipListeners(ToolTipEvent.HIDDEN);
alpha = 0;
}
@Override
public String getTipText() {
String text = super.getTipText();
if (text == null && getComponent() != null) {
return getComponent().getToolTipText();
}
return text;
}
@Override
public void propertyChange(final PropertyChangeEvent evt) {
if (DarkTooltipUI.TIP_TEXT_PROPERTY.equals(evt.getPropertyName())) {
setPreferredSize(getUI().getPreferredSize(this));
if (!Objects.equals(evt.getNewValue(), evt.getOldValue())) {
notifyToolTipListeners(ToolTipEvent.TEXT);
}
}
}
public void setStyle(final ToolTipStyle style) {
putClientProperty(DarkTooltipUI.KEY_STYLE, style);
}
private enum ToolTipEvent {
TEXT,
SHOWN,
HIDDEN
}
protected class FadeInAnimator extends Animator {
private static final int DELAY_FRAMES = 6;
private static final int FADEIN_FRAMES_COUNT = DELAY_FRAMES + 10;
public FadeInAnimator() {
super("Tooltip fadein", FADEIN_FRAMES_COUNT, FADEIN_FRAMES_COUNT * 15, false);
}
@Override
public void paintNow(final int frame, final int totalFrames, final int cycle) {
alpha = ((float) frame * MAX_ALPHA) / totalFrames;
paintImmediately(0, 0, getWidth(), getHeight());
}
@Override
protected void paintCycleEnd() {
alpha = MAX_ALPHA;
paintImmediately(0, 0, getWidth(), getHeight());
}
}
}

279
core/src/main/java/com/github/weisj/darklaf/components/tooltip/ToolTipContext.java

@ -25,6 +25,7 @@ package com.github.weisj.darklaf.components.tooltip;
import com.github.weisj.darklaf.components.alignment.AlignmentStrategy; import com.github.weisj.darklaf.components.alignment.AlignmentStrategy;
import com.github.weisj.darklaf.ui.tooltip.DarkTooltipBorder; import com.github.weisj.darklaf.ui.tooltip.DarkTooltipBorder;
import com.github.weisj.darklaf.ui.tooltip.DarkTooltipUI;
import com.github.weisj.darklaf.util.Alignment; import com.github.weisj.darklaf.util.Alignment;
import com.github.weisj.darklaf.util.DarkUIUtil; import com.github.weisj.darklaf.util.DarkUIUtil;
@ -34,26 +35,12 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
import java.awt.geom.Area; import java.awt.geom.Area;
import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
public class ToolTipContext implements ToolTipListener { public class ToolTipContext {
private final Insets calcInsets = new Insets(0, 0, 0, 0); private final Insets calcInsets = new Insets(0, 0, 0, 0);
private final JComponent c; private JComponent target;
private DarkToolTip toolTip;
private Alignment alignment;
private Alignment centerAlignment;
private boolean alignInside;
private boolean updatePosition;
private AlignmentStrategy alignmentStrategy;
private Function<MouseEvent, Rectangle> toolTipRectSupplier;
private boolean applyInsetsToRect;
private Point lastPos;
private Rectangle lastRect;
private boolean valid;
private Area hotSpotArea;
private boolean hideOnExit;
private final MouseListener mouseListener = new MouseAdapter() { private final MouseListener mouseListener = new MouseAdapter() {
@Override @Override
public void mouseExited(final MouseEvent e) { public void mouseExited(final MouseEvent e) {
@ -73,44 +60,55 @@ public class ToolTipContext implements ToolTipListener {
ToolTipManager.sharedInstance().mousePressed(null); ToolTipManager.sharedInstance().mousePressed(null);
} }
} else { } else {
if (!c.contains(e.getPoint())) { if (target != null && !target.contains(e.getPoint())) {
ToolTipManager.sharedInstance().mousePressed(null); ToolTipManager.sharedInstance().mousePressed(null);
} }
} }
} }
}; };
private Alignment alignment;
private Alignment centerAlignment;
private boolean alignInside;
private AlignmentStrategy alignmentStrategy;
private Function<MouseEvent, Rectangle> toolTipRectSupplier;
private boolean applyInsetsToRect;
private Area hotSpotArea;
private boolean hideOnExit;
private JToolTip toolTip;
private Insets insets; private Insets insets;
private ToolTipStyle style; private ToolTipStyle style;
/** /**
* Create a new tooltip context to ease the creation of custom tooltips. * Create a new tooltip context to ease the creation of custom tooltips.
*
* @param c the component which the tooltip belongs to.
*/ */
public ToolTipContext() {
this(null, null, null, null, true, null);
}
public ToolTipContext(final JComponent c) { /**
this(c, null, null, null, true, null); * Create a new tooltip context to ease the creation of custom tooltips.
*
* @param target the component which the tooltip belongs to.
*/
public ToolTipContext(final JComponent target) {
this(target, null, null, null, true, null);
} }
/** /**
* Create a new tooltip context to ease the creation of custom tooltips. * Create a new tooltip context to ease the creation of custom tooltips.
* *
* @param c the component which the tooltip belongs to. * @param target the component which the tooltip belongs to.
* @param alignment {@link #setAlignment(Alignment)} * @param alignment {@link #setAlignment(Alignment)}
* @param centerAlignment {@link #setCenterAlignment(Alignment)} * @param centerAlignment {@link #setCenterAlignment(Alignment)}
* @param alignmentStrategy {@link #setAlignmentStrategy(AlignmentStrategy)} * @param alignmentStrategy {@link #setAlignmentStrategy(AlignmentStrategy)}
* @param alignInside {@link #setAlignInside(boolean)} * @param alignInside {@link #setAlignInside(boolean)}
* @param toolTipRectSupplier {@link #setToolTipRectSupplier(Function)} * @param toolTipRectSupplier {@link #setToolTipRectSupplier(Function)}
*/ */
public ToolTipContext(final JComponent target, final Alignment alignment, final Alignment centerAlignment,
public ToolTipContext(final JComponent c, final Alignment alignment, final Alignment centerAlignment,
final AlignmentStrategy alignmentStrategy, final AlignmentStrategy alignmentStrategy,
final boolean alignInside, final Function<MouseEvent, Rectangle> toolTipRectSupplier) { final boolean alignInside, final Function<MouseEvent, Rectangle> toolTipRectSupplier) {
if (c == null) { this.target = target;
throw new IllegalArgumentException("Component is null");
}
this.c = c;
valid = false;
setToolTipStyle(ToolTipStyle.BALLOON); setToolTipStyle(ToolTipStyle.BALLOON);
setUpdatePosition(false); setUpdatePosition(false);
setHideOnExit(false); setHideOnExit(false);
@ -133,7 +131,6 @@ public class ToolTipContext implements ToolTipListener {
if (style == null) { if (style == null) {
this.style = ToolTipStyle.BALLOON; this.style = ToolTipStyle.BALLOON;
} }
updateToolTip();
return this; return this;
} }
@ -147,26 +144,18 @@ public class ToolTipContext implements ToolTipListener {
* @return this * @return this
*/ */
public ToolTipContext setUpdatePosition(final boolean updatePosition) { public ToolTipContext setUpdatePosition(final boolean updatePosition) {
this.updatePosition = updatePosition;
return this; return this;
} }
/** /**
* Sets whether the tooltip should be closed if the mouse has left the area set by {@link #setInsideArea(Area)}. * Create a new tooltip context to ease the creation of custom tooltips.
* <p>
* Default is false.
* *
* @param hideOnExit true if tooltip should hide. * @param target the component which the tooltip belongs to.
* @return this. * @param alignment {@link #setAlignment(Alignment)}
*/ */
public ToolTipContext setHideOnExit(final boolean hideOnExit) {
this.hideOnExit = hideOnExit; public ToolTipContext(final JComponent target, final Alignment alignment) {
if (hideOnExit) { this(target, alignment, null, null, true, null);
c.addMouseListener(mouseListener);
} else {
c.removeMouseListener(mouseListener);
}
return this;
} }
/** /**
@ -198,7 +187,6 @@ public class ToolTipContext implements ToolTipListener {
if (alignment == null) { if (alignment == null) {
this.alignment = Alignment.CENTER; this.alignment = Alignment.CENTER;
} }
updateToolTip();
return this; return this;
} }
@ -216,7 +204,6 @@ public class ToolTipContext implements ToolTipListener {
if (centerAlignment == null) { if (centerAlignment == null) {
this.centerAlignment = Alignment.NORTH; this.centerAlignment = Alignment.NORTH;
} }
updateToolTip();
return this; return this;
} }
@ -238,120 +225,131 @@ public class ToolTipContext implements ToolTipListener {
return this; return this;
} }
/**
* Set the supplier for the rectangle which is used to calculate the location of the tooltip. The coordinates should
* be relative to the components origin.
* <p>
* Default will be the component bounding rectangle.
*
* @param toolTipRectSupplier rectangle supplier method.
* @return this
*/
public ToolTipContext setToolTipRectSupplier(final Function<MouseEvent, Rectangle> toolTipRectSupplier) {
this.toolTipRectSupplier = toolTipRectSupplier;
if (toolTipRectSupplier == null) {
this.toolTipRectSupplier = e -> new Rectangle(0, 0, c.getWidth(), c.getHeight());
}
return this;
}
private void updateToolTip() {
if (toolTip != null) {
toolTip.setAlignment(alignment == Alignment.CENTER
? centerAlignment.opposite()
: alignInside ? alignment : alignment.opposite());
toolTip.setInsets(insets);
toolTip.setStyle(style);
}
}
/**
* Create a new tooltip context to ease the creation of custom tooltips.
*
* @param c the component which the tooltip belongs to.
* @param alignment {@link #setAlignment(Alignment)}
*/
public ToolTipContext(final JComponent c, final Alignment alignment) {
this(c, alignment, null, null, true, null);
}
/** /**
* Create a new tooltip context to ease the creation of custom tooltips. * Create a new tooltip context to ease the creation of custom tooltips.
* *
* @param c the component which the tooltip belongs to. * @param target the component which the tooltip belongs to.
* @param alignment {@link #setAlignment(Alignment)} * @param alignment {@link #setAlignment(Alignment)}
* @param centerAlignment {@link #setCenterAlignment(Alignment)} * @param centerAlignment {@link #setCenterAlignment(Alignment)}
*/ */
public ToolTipContext(final JComponent c, final Alignment alignment, final Alignment centerAlignment) { public ToolTipContext(final JComponent target, final Alignment alignment, final Alignment centerAlignment) {
this(c, alignment, centerAlignment, null, true, null); this(target, alignment, centerAlignment, null, true, null);
} }
/** /**
* Create a new tooltip context to ease the creation of custom tooltips. * Create a new tooltip context to ease the creation of custom tooltips.
* *
* @param c the component which the tooltip belongs to. * @param target the component which the tooltip belongs to.
* @param alignment {@link #setAlignment(Alignment)} * @param alignment {@link #setAlignment(Alignment)}
* @param alignInside {@link #setAlignInside(boolean)} * @param alignInside {@link #setAlignInside(boolean)}
*/ */
public ToolTipContext(final JComponent c, final Alignment alignment, final boolean alignInside) { public ToolTipContext(final JComponent target, final Alignment alignment, final boolean alignInside) {
this(c, alignment, null, null, alignInside, null); this(target, alignment, null, null, alignInside, null);
} }
/** /**
* Create a new tooltip context to ease the creation of custom tooltips. * Create a new tooltip context to ease the creation of custom tooltips.
* *
* @param c the component which the tooltip belongs to. * @param target the component which the tooltip belongs to.
* @param alignment {@link #setAlignment(Alignment)} * @param alignment {@link #setAlignment(Alignment)}
* @param centerAlignment {@link #setCenterAlignment(Alignment)} * @param centerAlignment {@link #setCenterAlignment(Alignment)}
* @param alignInside {@link #setAlignInside(boolean)} * @param alignInside {@link #setAlignInside(boolean)}
*/ */
public ToolTipContext(final JComponent c, final Alignment alignment, final Alignment centerAlignment, public ToolTipContext(final JComponent target, final Alignment alignment, final Alignment centerAlignment,
final boolean alignInside) { final boolean alignInside) {
this(c, alignment, centerAlignment, null, alignInside, null); this(target, alignment, centerAlignment, null, alignInside, null);
} }
/** /**
* Create a new tooltip context to ease the creation of custom tooltips. * Create a new tooltip context to ease the creation of custom tooltips.
* *
* @param c the component which the tooltip belongs to. * @param target the component which the tooltip belongs to.
* @param alignment {@link #setAlignment(Alignment)} * @param alignment {@link #setAlignment(Alignment)}
* @param alignmentStrategy {@link #setAlignmentStrategy(AlignmentStrategy)} * @param alignmentStrategy {@link #setAlignmentStrategy(AlignmentStrategy)}
*/ */
public ToolTipContext(final JComponent c, final Alignment alignment, final AlignmentStrategy alignmentStrategy) { public ToolTipContext(final JComponent target, final Alignment alignment, final AlignmentStrategy alignmentStrategy) {
this(c, alignment, null, alignmentStrategy, true, null); this(target, alignment, null, alignmentStrategy, true, null);
} }
/** /**
* Create a new tooltip context to ease the creation of custom tooltips. * Create a new tooltip context to ease the creation of custom tooltips.
* *
* @param c the component which the tooltip belongs to. * @param target the component which the tooltip belongs to.
* @param alignment {@link #setAlignment(Alignment)} * @param alignment {@link #setAlignment(Alignment)}
* @param centerAlignment {@link #setCenterAlignment(Alignment)} * @param centerAlignment {@link #setCenterAlignment(Alignment)}
* @param alignmentStrategy {@link #setAlignmentStrategy(AlignmentStrategy)} * @param alignmentStrategy {@link #setAlignmentStrategy(AlignmentStrategy)}
*/ */
public ToolTipContext(final JComponent c, final Alignment alignment, final Alignment centerAlignment, public ToolTipContext(final JComponent target, final Alignment alignment, final Alignment centerAlignment,
final AlignmentStrategy alignmentStrategy) { final AlignmentStrategy alignmentStrategy) {
this(c, alignment, centerAlignment, alignmentStrategy, true, null); this(target, alignment, centerAlignment, alignmentStrategy, true, null);
} }
/** /**
* Create a new tooltip context to ease the creation of custom tooltips. * Create a new tooltip context to ease the creation of custom tooltips.
* *
* @param c the component which the tooltip belongs to. * @param target the component which the tooltip belongs to.
* @param alignment {@link #setAlignment(Alignment)} * @param alignment {@link #setAlignment(Alignment)}
* @param alignmentStrategy {@link #setAlignmentStrategy(AlignmentStrategy)} * @param alignmentStrategy {@link #setAlignmentStrategy(AlignmentStrategy)}
* @param alignInside {@link #setAlignInside(boolean)} * @param alignInside {@link #setAlignInside(boolean)}
*/ */
public ToolTipContext(final JComponent c, final Alignment alignment, final AlignmentStrategy alignmentStrategy, public ToolTipContext(final JComponent target, final Alignment alignment, final AlignmentStrategy alignmentStrategy,
final boolean alignInside) { final boolean alignInside) {
this(c, alignment, null, alignmentStrategy, alignInside, null); this(target, alignment, null, alignmentStrategy, alignInside, null);
}
/**
* Sets whether the tooltip should be closed if the mouse has left the area set by {@link #setInsideArea(Area)}.
* <p>
* Default is false.
*
* @param hideOnExit true if tooltip should hide.
* @return this.
*/
public ToolTipContext setHideOnExit(final boolean hideOnExit) {
this.hideOnExit = hideOnExit;
if (target != null) {
if (hideOnExit) {
target.addMouseListener(mouseListener);
} else {
target.removeMouseListener(mouseListener);
}
}
return this;
}
/**
* Set the supplier for the rectangle which is used to calculate the location of the tooltip. The coordinates should
* be relative to the components origin.
* <p>
* Default will be the component bounding rectangle.
*
* @param toolTipRectSupplier rectangle supplier method.
* @return this
*/
public ToolTipContext setToolTipRectSupplier(final Function<MouseEvent, Rectangle> toolTipRectSupplier) {
this.toolTipRectSupplier = toolTipRectSupplier;
if (toolTipRectSupplier == null) {
this.toolTipRectSupplier = e -> new Rectangle(0, 0, target.getWidth(), target.getHeight());
}
return this;
}
public void updateToolTip() {
if (toolTip != null) {
toolTip.putClientProperty(DarkTooltipUI.KEY_POINTER_LOCATION,
alignment == Alignment.CENTER
? centerAlignment.opposite()
: alignInside ? alignment : alignment.opposite());
toolTip.putClientProperty(DarkTooltipUI.KEY_INSETS, insets);
toolTip.putClientProperty(DarkTooltipUI.KEY_STYLE, style);
toolTip.doLayout();
}
} }
/** /**
@ -400,30 +398,32 @@ public class ToolTipContext implements ToolTipListener {
*/ */
public ToolTipContext setToolTipInsets(final Insets insets) { public ToolTipContext setToolTipInsets(final Insets insets) {
this.insets = insets; this.insets = insets;
updateToolTip();
return this; return this;
} }
public Point getToolTipLocation(final MouseEvent event) {
Point mp = SwingUtilities.convertPoint((Component) event.getSource(), event.getPoint(), target);
return getToolTipLocation(mp, event);
}
/** /**
* Calculates the tooltip location. * Calculates the tooltip location.
* *
* @param event the mouse event. * @param mp the mouse position in the target component coordinate space.
* @param mouseEvent the mouse event.
* @return the tooltip location. * @return the tooltip location.
* @see JComponent#getToolTipLocation(MouseEvent) * @see JComponent#getToolTipLocation(MouseEvent)
*/ */
public Point getToolTipLocation(final MouseEvent event) { public Point getToolTipLocation(final Point mp, final MouseEvent mouseEvent) {
if (target == null) return null;
updateToolTip();
MouseEvent event = processEvent(mouseEvent, mp);
Rectangle rect = toolTipRectSupplier.apply(event); Rectangle rect = toolTipRectSupplier.apply(event);
if (applyInsetsToRect) { if (applyInsetsToRect) {
DarkUIUtil.applyInsets(rect, c.getInsets(calcInsets)); DarkUIUtil.applyInsets(rect, target.getInsets(calcInsets));
}
if (valid && !updatePosition
&& lastPos != null
&& !Objects.equals(rect, lastRect)) {
return lastPos;
} }
getToolTip().setTipText(c.getToolTipText(event)); getToolTip().setTipText(target.getToolTipText(event));
Dimension dim = getContentSize(); Dimension dim = getContentSize();
Point mp = SwingUtilities.convertPoint((Component) event.getSource(), event.getPoint(), c);
Rectangle mRect = new Rectangle(mp.x, mp.y, 1, 1); Rectangle mRect = new Rectangle(mp.x, mp.y, 1, 1);
Point compPoint; Point compPoint;
Point mousePoint; Point mousePoint;
@ -437,31 +437,38 @@ public class ToolTipContext implements ToolTipListener {
: alignOutside(dim, mRect); : alignOutside(dim, mRect);
} }
lastPos = alignmentStrategy.align(compPoint, mousePoint); return alignmentStrategy.align(compPoint, mousePoint);
lastRect = rect; }
valid = true;
return lastPos; private MouseEvent processEvent(final MouseEvent mouseEvent, final Point mp) {
if (mouseEvent != null) return mouseEvent;
return new MouseEvent(target, MouseEvent.MOUSE_MOVED, System.currentTimeMillis(), 0, mp.x, mp.y,
0, false, 0);
}
public JComponent getTarget() {
return target;
}
public void setTarget(final JComponent target) {
this.target = target;
} }
/** /**
* Get the tooltip. * Get the tooltip.
* *
* @see JComponent#createToolTip()
* @return the tooltip. * @return the tooltip.
* @see JComponent#createToolTip()
*/ */
public JToolTip getToolTip() { public JToolTip getToolTip() {
if (toolTip == null) { if (toolTip == null) {
toolTip = new DarkToolTip(alignment); setToolTip(new JToolTip());
toolTip.addToolTipListener(this);
toolTip.setComponent(this.c);
updateToolTip();
} }
return toolTip; return toolTip;
} }
public void updateToolTipUI() { public void updateToolTipUI() {
if (toolTip != null) toolTip.updateUI(); if (toolTip != null) toolTip.updateUI();
updateToolTip();
} }
private Dimension getContentSize() { private Dimension getContentSize() {
@ -509,24 +516,6 @@ public class ToolTipContext implements ToolTipListener {
setHideOnExit(false); setHideOnExit(false);
} }
@Override
public void toolTipShown(final JToolTip toolTip) {
}
@Override
public void toolTipHidden(final JToolTip toolTip) {
if (toolTip == this.toolTip) {
valid = false;
}
}
@Override
public void textChanged(final JToolTip toolTip) {
if (toolTip == this.toolTip) {
valid = false;
}
}
public Alignment getAlignment() { public Alignment getAlignment() {
return alignment; return alignment;
} }
@ -542,4 +531,12 @@ public class ToolTipContext implements ToolTipListener {
public boolean isAlignInside() { public boolean isAlignInside() {
return alignInside; return alignInside;
} }
public void setToolTip(final JToolTip toolTip) {
if (toolTip == null) return;
this.toolTip = toolTip;
if (this.target != toolTip.getComponent()) {
this.toolTip.setComponent(this.target);
}
}
} }

36
core/src/main/java/com/github/weisj/darklaf/components/tooltip/ToolTipListener.java

@ -1,36 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* 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:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* 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.github.weisj.darklaf.components.tooltip;
import javax.swing.*;
import java.util.EventListener;
public interface ToolTipListener extends EventListener {
void toolTipShown(JToolTip toolTip);
void toolTipHidden(JToolTip toolTip);
void textChanged(JToolTip toolTip);
}

1
core/src/main/java/com/github/weisj/darklaf/components/tooltip/ToolTipStyle.java

@ -25,5 +25,6 @@ package com.github.weisj.darklaf.components.tooltip;
public enum ToolTipStyle { public enum ToolTipStyle {
BALLOON, BALLOON,
PLAIN_BALLOON,
PLAIN, PLAIN,
} }

9
core/src/main/java/com/github/weisj/darklaf/ui/BasicTransferable.java

@ -28,11 +28,8 @@ import javax.swing.plaf.UIResource;
import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable; import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException; import java.io.*;
import java.io.InputStream; import java.util.logging.Logger;
import java.io.Reader;
import java.io.StringBufferInputStream;
import java.io.StringReader;
/** /**
* A transferable implementation for the default data transfer of some Swing components. * A transferable implementation for the default data transfer of some Swing components.
@ -63,7 +60,7 @@ public class BasicTransferable implements Transferable, UIResource {
stringFlavors[1] = DataFlavor.stringFlavor; stringFlavors[1] = DataFlavor.stringFlavor;
} catch (ClassNotFoundException cle) { } catch (ClassNotFoundException cle) {
System.err.println("error initializing javax.swing.plaf.basic.BasicTranserable"); Logger.getGlobal().severe("error initializing javax.swing.plaf.basic.BasicTranserable");
} }
} }

6
core/src/main/java/com/github/weisj/darklaf/ui/DarkPopupFactory.java

@ -36,12 +36,14 @@ public class DarkPopupFactory extends PopupFactory {
public Popup getPopup(final Component owner, final Component contents, public Popup getPopup(final Component owner, final Component contents,
final int x, final int y) throws IllegalArgumentException { final int x, final int y) throws IllegalArgumentException {
Popup popup = super.getPopup(owner, contents, x, y); Popup popup = super.getPopup(owner, contents, x, y);
if (popup.getClass().getSimpleName().endsWith("MediumWeightPopup")) { boolean isMediumWeight = popup.getClass().getSimpleName().endsWith("MediumWeightPopup");
boolean isLightWeight = popup.getClass().getSimpleName().endsWith("LightWeightPopup");
if (isMediumWeight || isLightWeight) {
if (contents instanceof JToolTip if (contents instanceof JToolTip
&& ((JToolTip) contents).getBorder() instanceof DarkTooltipBorder) { && ((JToolTip) contents).getBorder() instanceof DarkTooltipBorder) {
// null owner forces a heavyweight popup. // null owner forces a heavyweight popup.
popup = super.getPopup(null, contents, x, y); popup = super.getPopup(null, contents, x, y);
} else { } else if (isMediumWeight) {
JRootPane rootPane = SwingUtilities.getRootPane(contents); JRootPane rootPane = SwingUtilities.getRootPane(contents);
// Prevents decorations from being reinstalled. // Prevents decorations from being reinstalled.
if (rootPane != null) rootPane.putClientProperty(DarkRootPaneUI.KEY_IS_MEDIUM_WEIGHT_POPUP_ROOT, true); if (rootPane != null) rootPane.putClientProperty(DarkRootPaneUI.KEY_IS_MEDIUM_WEIGHT_POPUP_ROOT, true);

19
core/src/main/java/com/github/weisj/darklaf/ui/tooltip/DarkTooltipBorder.java

@ -28,6 +28,7 @@ import com.github.weisj.darklaf.components.border.DropShadowBorder;
import com.github.weisj.darklaf.components.tooltip.ToolTipStyle; import com.github.weisj.darklaf.components.tooltip.ToolTipStyle;
import com.github.weisj.darklaf.util.Alignment; import com.github.weisj.darklaf.util.Alignment;
import com.github.weisj.darklaf.util.DarkUIUtil; import com.github.weisj.darklaf.util.DarkUIUtil;
import com.github.weisj.darklaf.util.GraphicsContext;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.Border; import javax.swing.border.Border;
@ -45,6 +46,7 @@ public class DarkTooltipBorder implements Border {
false, true, false, true,
true, true); true, true);
private final BubbleBorder bubbleBorder; private final BubbleBorder bubbleBorder;
private static final AlphaComposite COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
public DarkTooltipBorder() { public DarkTooltipBorder() {
bubbleBorder = new BubbleBorder(UIManager.getColor("ToolTip.borderColor")); bubbleBorder = new BubbleBorder(UIManager.getColor("ToolTip.borderColor"));
@ -86,9 +88,25 @@ public class DarkTooltipBorder implements Border {
} }
} }
protected float getAlpha(final Component c) {
if (c instanceof JComponent) {
Object alpha = ((JComponent) c).getClientProperty(DarkTooltipUI.KEY_PAINT_ALPHA);
if (alpha instanceof Float) {
return (float) alpha;
}
}
return DarkTooltipUI.MAX_ALPHA;
}
@Override @Override
public void paintBorder(final Component c, final Graphics g, public void paintBorder(final Component c, final Graphics g,
final int x, final int y, final int width, final int height) { final int x, final int y, final int width, final int height) {
float alpha = getAlpha(c);
if (alpha == 0) return;
GraphicsContext context = new GraphicsContext(g);
if (alpha != DarkTooltipUI.MAX_ALPHA) {
((Graphics2D) g).setComposite(COMPOSITE.derive(alpha));
}
if (isPlain(c)) { if (isPlain(c)) {
g.setColor(bubbleBorder.getColor()); g.setColor(bubbleBorder.getColor());
DarkUIUtil.drawRect(g, x, y, width, height, 1); DarkUIUtil.drawRect(g, x, y, width, height, 1);
@ -115,6 +133,7 @@ public class DarkTooltipBorder implements Border {
shadowBorder.paintBorder(c, g, x + bw, y + bw + off, width - 2 * bw, height - 2 * bw - off); shadowBorder.paintBorder(c, g, x + bw, y + bw + off, width - 2 * bw, height - 2 * bw - off);
g.setClip(oldClip); g.setClip(oldClip);
bubbleBorder.paintBorder(g, bubbleArea); bubbleBorder.paintBorder(g, bubbleArea);
context.restore();
} }
@Override @Override

65
core/src/main/java/com/github/weisj/darklaf/ui/tooltip/DarkTooltipUI.java

@ -25,9 +25,7 @@ package com.github.weisj.darklaf.ui.tooltip;
import com.github.weisj.darklaf.components.tooltip.ToolTipStyle; import com.github.weisj.darklaf.components.tooltip.ToolTipStyle;
import com.github.weisj.darklaf.ui.rootpane.DarkRootPaneUI; import com.github.weisj.darklaf.ui.rootpane.DarkRootPaneUI;
import com.github.weisj.darklaf.util.Alignment; import com.github.weisj.darklaf.util.*;
import com.github.weisj.darklaf.util.DarkUIUtil;
import com.github.weisj.darklaf.util.PropertyKey;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.Border; import javax.swing.border.Border;
@ -55,6 +53,12 @@ public class DarkTooltipUI extends BasicToolTipUI implements PropertyChangeListe
public static final String VARIANT_PLAIN = "plain"; public static final String VARIANT_PLAIN = "plain";
public static final String VARIANT_BALLOON = "balloon"; public static final String VARIANT_BALLOON = "balloon";
public static final String TIP_TEXT_PROPERTY = "tiptext"; public static final String TIP_TEXT_PROPERTY = "tiptext";
public static final String KEY_PAINT_ALPHA = KEY_PREFIX + "paintAlpha";
public static final String KEY_CONTEXT = KEY_PREFIX + "toolTipContext";
static final float MAX_ALPHA = 1.0f;
private static final AlphaComposite COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
private Animator fadeAnimator;
private float alpha = 0;
protected JToolTip toolTip; protected JToolTip toolTip;
protected JRootPane lastRootPane; protected JRootPane lastRootPane;
@ -103,6 +107,7 @@ public class DarkTooltipUI extends BasicToolTipUI implements PropertyChangeListe
updateStyle(); updateStyle();
} }
}; };
private boolean added;
public static ComponentUI createUI(final JComponent c) { public static ComponentUI createUI(final JComponent c) {
@ -151,6 +156,7 @@ public class DarkTooltipUI extends BasicToolTipUI implements PropertyChangeListe
@Override @Override
protected void installDefaults(final JComponent c) { protected void installDefaults(final JComponent c) {
super.installDefaults(c); super.installDefaults(c);
fadeAnimator = new FadeInAnimator();
c.setOpaque(false); c.setOpaque(false);
DarkTooltipBorder border = new DarkTooltipBorder(); DarkTooltipBorder border = new DarkTooltipBorder();
Alignment align = (Alignment) c.getClientProperty(KEY_POINTER_LOCATION); Alignment align = (Alignment) c.getClientProperty(KEY_POINTER_LOCATION);
@ -186,12 +192,25 @@ public class DarkTooltipUI extends BasicToolTipUI implements PropertyChangeListe
@Override @Override
public void paint(final Graphics g, final JComponent c) { public void paint(final Graphics g, final JComponent c) {
if (((JToolTip) c).getTipText() == null) return; if (((JToolTip) c).getTipText() == null) return;
if (added) {
added = false;
alpha = 0;
fadeAnimator.reset();
fadeAnimator.resume();
}
toolTip.putClientProperty(KEY_PAINT_ALPHA, alpha);
if (alpha == 0) return;
GraphicsContext config = new GraphicsContext(g);
if (alpha != MAX_ALPHA) {
((Graphics2D) g).setComposite(COMPOSITE.derive(alpha));
}
g.setColor(c.getBackground()); g.setColor(c.getBackground());
if (c.getBorder() instanceof DarkTooltipBorder) { if (c.getBorder() instanceof DarkTooltipBorder) {
Area area = ((DarkTooltipBorder) c.getBorder()).getBackgroundArea(c, c.getWidth(), c.getHeight()); Area area = ((DarkTooltipBorder) c.getBorder()).getBackgroundArea(c, c.getWidth(), c.getHeight());
((Graphics2D) g).fill(area); ((Graphics2D) g).fill(area);
} }
super.paint(g, c); super.paint(g, c);
config.restore();
} }
public Dimension getPreferredSize(final JComponent c) { public Dimension getPreferredSize(final JComponent c) {
@ -301,6 +320,15 @@ public class DarkTooltipUI extends BasicToolTipUI implements PropertyChangeListe
updateSize(); updateSize();
isTipTextChanging = false; isTipTextChanging = false;
} }
} else if (PropertyKey.ANCESTOR.equals(key)) {
if (evt.getOldValue() == null) {
//Added to hierarchy. Schedule animation start.
added = true;
ToolTipUtil.applyContext(toolTip);
}
if (evt.getNewValue() == null) {
alpha = 0;
}
} }
} }
if (KEY_STYLE.equals(key)) { if (KEY_STYLE.equals(key)) {
@ -316,19 +344,34 @@ public class DarkTooltipUI extends BasicToolTipUI implements PropertyChangeListe
Object tooltipStyle = toolTip.getClientProperty(KEY_STYLE); Object tooltipStyle = toolTip.getClientProperty(KEY_STYLE);
toolTip.putClientProperty(KEY_STYLE, style instanceof ToolTipStyle ? style : toolTip.putClientProperty(KEY_STYLE, style instanceof ToolTipStyle ? style :
tooltipStyle instanceof ToolTipStyle ? tooltipStyle tooltipStyle instanceof ToolTipStyle ? tooltipStyle
: ToolTipStyle.BALLOON); : ToolTipStyle.PLAIN_BALLOON);
} }
} }
protected ToolTipStyle getStyle() {
Object prop = toolTip.getClientProperty(KEY_STYLE);
String propValue = prop != null ? prop.toString() : null;
if (ToolTipStyle.BALLOON.name().equals(propValue)) return ToolTipStyle.BALLOON;
return ToolTipStyle.PLAIN;
}
protected void updateSize() { protected void updateSize() {
toolTip.setTipText(toolTip.getTipText()); toolTip.setTipText(toolTip.getTipText());
toolTip.setPreferredSize(getPreferredSize(toolTip)); toolTip.setPreferredSize(getPreferredSize(toolTip));
} }
protected class FadeInAnimator extends Animator {
private static final int DELAY_FRAMES = 6;
private static final int FADEIN_FRAMES_COUNT = DELAY_FRAMES + 10;
public FadeInAnimator() {
super("Tooltip fadein", FADEIN_FRAMES_COUNT, FADEIN_FRAMES_COUNT * 20, false);
}
@Override
public void paintNow(final int frame, final int totalFrames, final int cycle) {
alpha = ((float) frame * MAX_ALPHA) / totalFrames;
toolTip.paintImmediately(0, 0, toolTip.getWidth(), toolTip.getHeight());
}
@Override
protected void paintCycleEnd() {
alpha = MAX_ALPHA;
toolTip.paintImmediately(0, 0, toolTip.getWidth(), toolTip.getHeight());
}
}
} }

179
core/src/main/java/com/github/weisj/darklaf/ui/tooltip/ToolTipUtil.java

@ -0,0 +1,179 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* 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:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* 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.github.weisj.darklaf.ui.tooltip;
import com.github.weisj.darklaf.components.alignment.AlignmentStrategy;
import com.github.weisj.darklaf.components.tooltip.ToolTipContext;
import com.github.weisj.darklaf.components.tooltip.ToolTipStyle;
import com.github.weisj.darklaf.util.Alignment;
import com.github.weisj.darklaf.util.DarkUIUtil;
import javax.swing.*;
import java.awt.*;
public class ToolTipUtil {
private final static ToolTipContext DEFAULT_CONTEXT = new ToolTipContext().setAlignment(Alignment.CENTER)
.setCenterAlignment(Alignment.SOUTH);
public static void applyContext(final JToolTip toolTip) {
JComponent target = toolTip.getComponent();
if (target == null) return;
ToolTipContext context = getToolTipContext(target);
if (context == null) return;
context.setTarget(target);
context.setToolTip(toolTip);
Point p = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(p, target);
Point pos = getBestPositionMatch(context, p);
if (pos != null) {
moveToolTip(toolTip, pos.x, pos.y, target);
}
}
protected static Point getBestPositionMatch(final ToolTipContext context, final Point p) {
if (context.getAlignment() != Alignment.CENTER
|| context.getAlignmentStrategy() != AlignmentStrategy.COMPONENT_BOTH) {
return context.getToolTipLocation(p, null);
}
// For now adjustments are only made when the alignment is in the center and no mouse coordinates are used.
Rectangle screenBounds = getScreenBounds(context.getTarget(), p);
Rectangle windowBounds = DarkUIUtil.getWindow(context.getTarget()).getBounds();
Rectangle tooltipBounds = new Rectangle();
tooltipBounds.setSize(context.getToolTip().getPreferredSize());
Alignment original = context.getCenterAlignment();
Alignment[] alignments = getAlignments(original);
Point pos = null;
// Check if a position keeps the tooltip inside the window.
for (Alignment a : alignments) {
pos = tryPosition(a, context, p, tooltipBounds, windowBounds, screenBounds);
if (pos != null) break;
}
if (pos == null) {
//Try again with screen bounds instead.
for (Alignment a : alignments) {
pos = tryPosition(a, context, p, tooltipBounds, screenBounds, screenBounds);
if (pos != null) break;
}
}
/*
* At this point if the tooltip is still extending outside the screen boundary
* we surrender and leave the tooltip as it was.
*/
if (pos == null) {
context.setCenterAlignment(Alignment.CENTER);
}
context.updateToolTip();
context.setCenterAlignment(original);
return pos;
}
protected static Alignment[] getAlignments(final Alignment start) {
//Example with NORTH:
return new Alignment[]{
start, //NORTH
start.opposite(), //SOUTH
start.clockwise().clockwise(),//EAST
start.anticlockwise().anticlockwise(), //WEST
start.clockwise(), //NORTH_EAST
start.clockwise().opposite(), //SOUTH_WEST
start.anticlockwise(), //NORTH_WEST
start.anticlockwise().opposite() //SOUTH_EAST
};
}
protected static Point tryPosition(final Alignment a, final ToolTipContext context, final Point p,
final Rectangle tooltipBounds, final Rectangle boundary,
final Rectangle screenBoundary) {
context.setCenterAlignment(a);
Point pos = context.getToolTipLocation(p, null);
Point screenPos = new Point(pos.x, pos.y);
SwingUtilities.convertPointToScreen(screenPos, context.getTarget());
tooltipBounds.setLocation(screenPos);
if (!fits(tooltipBounds, boundary, screenBoundary)) pos = null;
return pos;
}
protected static boolean fits(final Rectangle toolTipBounds, final Rectangle boundary,
final Rectangle screenBoundary) {
if (boundary == screenBoundary) {
return SwingUtilities.isRectangleContainingRectangle(boundary, toolTipBounds);
}
return SwingUtilities.isRectangleContainingRectangle(boundary, toolTipBounds)
&& SwingUtilities.isRectangleContainingRectangle(screenBoundary, toolTipBounds);
}
protected static ToolTipContext getToolTipContext(final JComponent comp) {
Object context = comp.getClientProperty(DarkTooltipUI.KEY_CONTEXT);
if (context instanceof ToolTipContext) {
return (ToolTipContext) context;
}
if (ToolTipStyle.BALLOON.equals(comp.getClientProperty(DarkTooltipUI.KEY_STYLE))) {
return DEFAULT_CONTEXT;
}
return null;
}
public static void moveToolTip(final JToolTip toolTip, final int x, final int y, final JComponent target) {
Window window = DarkUIUtil.getWindow(toolTip);
if (window == null) return;
Point targetPos = target.getLocationOnScreen();
window.setLocation(targetPos.x + x, targetPos.y + y);
}
protected static Rectangle getScreenBounds(final JComponent target, final Point p) {
GraphicsConfiguration gc = getDrawingGC(p);
if (gc == null) {
gc = target.getGraphicsConfiguration();
}
Rectangle sBounds = gc.getBounds();
Insets screenInsets = Toolkit.getDefaultToolkit()
.getScreenInsets(gc);
// Take into account screen insets, decrease viewport
sBounds.x += screenInsets.left;
sBounds.y += screenInsets.top;
sBounds.width -= (screenInsets.left + screenInsets.right);
sBounds.height -= (screenInsets.top + screenInsets.bottom);
return sBounds;
}
private static GraphicsConfiguration getDrawingGC(final Point location) {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] devices = env.getScreenDevices();
for (GraphicsDevice device : devices) {
GraphicsConfiguration config = device.getDefaultConfiguration();
Rectangle rect = config.getBounds();
if (rect.contains(location)) {
return config;
}
}
return null;
}
}

1
core/src/test/java/ui/dialog/DialogDemo.java

@ -441,7 +441,6 @@ public class DialogDemo extends JPanel {
if (imgURL != null) { if (imgURL != null) {
return new ImageIcon(imgURL); return new ImageIcon(imgURL);
} else { } else {
System.err.println("Couldn't find file: " + path);
return null; return null;
} }
} }

10
core/src/test/java/ui/toolTip/ToolTipDemo.java

@ -26,7 +26,7 @@ package ui.toolTip;
import com.github.weisj.darklaf.components.alignment.AlignmentStrategy; import com.github.weisj.darklaf.components.alignment.AlignmentStrategy;
import com.github.weisj.darklaf.components.tooltip.ToolTipContext; import com.github.weisj.darklaf.components.tooltip.ToolTipContext;
import com.github.weisj.darklaf.components.tooltip.ToolTipStyle; import com.github.weisj.darklaf.components.tooltip.ToolTipStyle;
import com.github.weisj.darklaf.components.tooltip.TooltipAwareButton; import com.github.weisj.darklaf.ui.tooltip.DarkTooltipUI;
import com.github.weisj.darklaf.util.Alignment; import com.github.weisj.darklaf.util.Alignment;
import ui.ComponentDemo; import ui.ComponentDemo;
import ui.DemoPanel; import ui.DemoPanel;
@ -41,10 +41,12 @@ public class ToolTipDemo implements ComponentDemo {
@Override @Override
public JComponent createComponent() { public JComponent createComponent() {
TooltipAwareButton button = new TooltipAwareButton("Demo Button"); JButton button = new JButton("Demo Button");
DemoPanel panel = new DemoPanel(button); DemoPanel panel = new DemoPanel(button);
ToolTipContext context = button.getToolTipContext(); ToolTipContext context = new ToolTipContext(button).setAlignment(Alignment.CENTER)
button.setToolTipText("ToolTip demo text!"); .setCenterAlignment(Alignment.SOUTH);
button.putClientProperty(DarkTooltipUI.KEY_CONTEXT, context);
button.setToolTipText("This is the ToolTip demo text!");
JPanel controlPanel = panel.addControls(); JPanel controlPanel = panel.addControls();

Loading…
Cancel
Save