00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package com.realtime.crossfire.jxclient.gui.label;
00023
00024 import com.realtime.crossfire.jxclient.gui.gui.AbstractGUIElement;
00025 import com.realtime.crossfire.jxclient.gui.gui.GUIElement;
00026 import com.realtime.crossfire.jxclient.gui.gui.GuiUtils;
00027 import com.realtime.crossfire.jxclient.gui.gui.TooltipManager;
00028 import com.realtime.crossfire.jxclient.gui.gui.TooltipText;
00029 import java.awt.Component;
00030 import java.util.WeakHashMap;
00031 import org.jetbrains.annotations.NotNull;
00032 import org.jetbrains.annotations.Nullable;
00033
00039 public class TooltipManagerImpl implements TooltipManager {
00040
00044 private static final int TOOLTIP_DISTANCE = 8;
00045
00049 private int windowWidth = 0;
00050
00054 private int windowHeight = 0;
00055
00060 @Nullable
00061 private AbstractLabel tooltip = null;
00062
00067 @Nullable
00068 private GUIElement activeGuiElement = null;
00069
00073 @NotNull
00074 private final Object activeGuiElementSync = new Object();
00075
00081 @NotNull
00082 private final WeakHashMap<GUIElement, TooltipText> tooltipTexts = new WeakHashMap<GUIElement, TooltipText>();
00083
00089 public void setScreenSize(final int windowWidth, final int windowHeight) {
00090 this.windowWidth = windowWidth;
00091 this.windowHeight = windowHeight;
00092 }
00093
00098 public void setTooltip(@Nullable final AbstractLabel tooltip) {
00099 this.tooltip = tooltip;
00100 }
00101
00105 public void reset() {
00106 synchronized (activeGuiElementSync) {
00107 removeTooltip();
00108 activeGuiElement = null;
00109 }
00110 }
00111
00115 @Override
00116 public void setElement(@NotNull final GUIElement guiElement) {
00117 final TooltipText tooltipText = tooltipTexts.get(guiElement);
00118 if (tooltipText != null) {
00119 guiElement.setTooltipText(tooltipText.getText());
00120 }
00121 synchronized (activeGuiElementSync) {
00122 if (activeGuiElement == null) {
00123 activeGuiElement = guiElement;
00124 addTooltip();
00125 } else if (activeGuiElement != guiElement) {
00126 removeTooltip();
00127 activeGuiElement = guiElement;
00128 addTooltip();
00129 }
00130 }
00131 }
00132
00136 @Override
00137 public void unsetElement(@NotNull final GUIElement guiElement) {
00138 synchronized (activeGuiElementSync) {
00139 if (activeGuiElement == guiElement) {
00140 removeTooltip();
00141 activeGuiElement = null;
00142 }
00143 }
00144 }
00145
00149 @Override
00150 public void setTooltipText(@NotNull final AbstractGUIElement element, @Nullable final String tooltipText) {
00151 final Component gui = GuiUtils.getGui(element);
00152 if (gui != null) {
00153 setTooltipText(element, tooltipText, gui.getX()+element.getX(), gui.getY()+element.getY(), element.getWidth(), element.getHeight());
00154 }
00155 }
00156
00160 @Override
00161 public void setTooltipText(@NotNull final GUIElement element, @Nullable final String tooltipText, final int x, final int y, final int w, final int h) {
00162 final TooltipText oldTooltipText = tooltipTexts.get(element);
00163 if (oldTooltipText == null) {
00164 if (tooltipText == null) {
00165 return;
00166 }
00167 } else {
00168 if (tooltipText != null && tooltipText.equals(oldTooltipText.getText()) && x == oldTooltipText.getX() && y == oldTooltipText.getY() && w == oldTooltipText.getW() && h == oldTooltipText.getH()) {
00169 return;
00170 }
00171 }
00172 tooltipTexts.put(element, tooltipText == null ? null : new TooltipText(tooltipText, x, y, w, h));
00173
00174 synchronized (activeGuiElementSync) {
00175 if (activeGuiElement == element) {
00176 removeTooltip();
00177 addTooltip();
00178 }
00179 }
00180 }
00181
00185 @Override
00186 public boolean hasTooltipText(final AbstractGUIElement element) {
00187 return tooltipTexts.get(element) != null;
00188 }
00189
00194 private void addTooltip() {
00195 final GUIElement tmpActiveGuiElement = activeGuiElement;
00196 assert tmpActiveGuiElement != null;
00197 assert Thread.holdsLock(activeGuiElementSync);
00198
00199 final AbstractLabel tmpTooltip = tooltip;
00200 if (tmpTooltip == null) {
00201 return;
00202 }
00203
00204 final TooltipText tooltipText = tooltipTexts.get(tmpActiveGuiElement);
00205 if (tooltipText == null) {
00206 tmpTooltip.setVisible(false);
00207 return;
00208 }
00209
00210 tmpTooltip.setVisible(true);
00211 tmpTooltip.setText(tooltipText.getText());
00212
00213 final int preferredX = tooltipText.getX()+tooltipText.getW()/2-tmpTooltip.getWidth()/2;
00214 final int maxX = windowWidth-tmpTooltip.getWidth();
00215 final int tx = Math.max(0, Math.min(preferredX, maxX));
00216 final int ty;
00217 final int elementY = tooltipText.getY();
00218 final int preferredY = elementY+tooltipText.getH()+TOOLTIP_DISTANCE;
00219 if (preferredY+tmpTooltip.getHeight() <= windowHeight) {
00220 ty = preferredY;
00221 } else {
00222 ty = elementY-tmpTooltip.getHeight()-TOOLTIP_DISTANCE;
00223 }
00224 tmpTooltip.setLocation(tx, ty);
00225 }
00226
00230 private void removeTooltip() {
00231 if (tooltip != null) {
00232 tooltip.setVisible(false);
00233 }
00234 }
00235
00236 }