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.log;
00023
00024 import com.realtime.crossfire.jxclient.gui.gui.AbstractGUIElement;
00025 import com.realtime.crossfire.jxclient.gui.gui.GUIElementListener;
00026 import com.realtime.crossfire.jxclient.gui.gui.TooltipManager;
00027 import com.realtime.crossfire.jxclient.gui.scrollable.GUIScrollable2;
00028 import com.realtime.crossfire.jxclient.gui.scrollable.ScrollableListener;
00029 import com.realtime.crossfire.jxclient.util.EventListenerList2;
00030 import java.awt.Color;
00031 import java.awt.Dimension;
00032 import java.awt.Graphics;
00033 import java.awt.Graphics2D;
00034 import java.awt.GraphicsEnvironment;
00035 import java.awt.Image;
00036 import java.awt.Transparency;
00037 import java.awt.font.FontRenderContext;
00038 import java.awt.image.BufferedImage;
00039 import java.util.ListIterator;
00040 import org.jetbrains.annotations.NotNull;
00041 import org.jetbrains.annotations.Nullable;
00042
00048 public abstract class GUILog extends AbstractGUIElement implements GUIScrollable2 {
00049
00053 private static final long serialVersionUID = 1;
00054
00058 private static final int SCROLL_PIXEL = 12;
00059
00063 @NotNull
00064 private final EventListenerList2<ScrollableListener> listeners = new EventListenerList2<ScrollableListener>(ScrollableListener.class);
00065
00069 @NotNull
00070 private final Buffer buffer;
00071
00076 @Nullable
00077 private final Image backgroundImage;
00078
00082 @NotNull
00083 private final Fonts fonts;
00084
00088 @NotNull
00089 private final RenderStateManager renderStateManager;
00090
00094 @NotNull
00095 private final RenderStateListener renderStateListener = new RenderStateListener() {
00096
00097 @Override
00098 public void stateChanged() {
00099 setChanged();
00100 for (final ScrollableListener listener : listeners.getListeners()) {
00101 listener.setRange(0, buffer.getTotalHeight(), renderStateManager.getScrollPos(), getHeight());
00102 }
00103 }
00104
00105 @Override
00106 public int getHeight() {
00107 return Math.max(1, GUILog.this.getHeight());
00108 }
00109
00110 };
00111
00121 protected GUILog(@NotNull final TooltipManager tooltipManager, @NotNull final GUIElementListener elementListener, @NotNull final String name, @Nullable final Image backgroundImage, @NotNull final Fonts fonts) {
00122 super(tooltipManager, elementListener, name, Transparency.TRANSLUCENT);
00123 this.backgroundImage = backgroundImage;
00124 this.fonts = fonts;
00125 final FontRenderContext context;
00126 final GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
00127 final Graphics2D g = graphicsEnvironment.createGraphics(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB));
00128 try {
00129 context = g.getFontRenderContext();
00130 } finally {
00131 g.dispose();
00132 }
00133 buffer = new Buffer(fonts, context, getWidth());
00134 renderStateManager = new RenderStateManager(renderStateListener, buffer);
00135 renderStateManager.setHeight(getHeight());
00136 }
00137
00141 @Override
00142 public void dispose() {
00143 super.dispose();
00144 renderStateManager.dispose();
00145 }
00146
00150 @Override
00151 public void execute() {
00152
00153 }
00154
00158 @Override
00159 public void paintComponent(@NotNull final Graphics g) {
00160 super.paintComponent(g);
00161
00162 g.setColor(new Color(0, 0, 0, 0.0f));
00163 g.fillRect(0, 0, getWidth(), getHeight());
00164 if (backgroundImage != null) {
00165 g.drawImage(backgroundImage, 0, 0, null);
00166 }
00167
00168 int y = -renderStateManager.getTopOffset();
00169 final int topIndex = renderStateManager.getTopIndex();
00170 synchronized (buffer.getSyncObject()) {
00171 final ListIterator<Line> it = buffer.listIterator(topIndex);
00172 while (y < getHeight() && it.hasNext()) {
00173 final Line line = it.next();
00174 drawLine(g, y, line);
00175 y += line.getHeight();
00176 }
00177 }
00178 }
00179
00186 private void drawLine(@NotNull final Graphics g, final int y, @NotNull final Iterable<Segment> line) {
00187 for (final Segment segment : line) {
00188 segment.draw(g, y, fonts);
00189 }
00190 }
00191
00195 @Override
00196 public boolean canScroll(final int distance) {
00197 if (distance < 0) {
00198 return renderStateManager.canScrollUp();
00199 } else if (distance > 0) {
00200 return renderStateManager.canScrollDown();
00201 } else {
00202 return false;
00203 }
00204 }
00205
00209 @Override
00210 public void scroll(final int distance) {
00211 if (distance < 0) {
00212 renderStateManager.scrollUp(-distance*SCROLL_PIXEL);
00213 } else if (distance > 0) {
00214 renderStateManager.scrollDown(distance*SCROLL_PIXEL);
00215 } else {
00216 assert false;
00217 }
00218 }
00219
00223 @Override
00224 public void resetScroll() {
00225 renderStateManager.resetScroll();
00226 }
00227
00231 @Override
00232 public void scrollTo(final int pos) {
00233 renderStateManager.scrollTo(pos);
00234 }
00235
00239 @Override
00240 public void addScrollableListener(@NotNull final ScrollableListener listener) {
00241 listeners.add(listener);
00242 }
00243
00247 @Override
00248 public void removeScrollableListener(@NotNull final ScrollableListener listener) {
00249 listeners.remove(listener);
00250 }
00251
00256 @NotNull
00257 public Buffer getBuffer() {
00258 return buffer;
00259 }
00260
00264 @Override
00265 public void setBounds(final int x, final int y, final int width, final int height) {
00266 super.setBounds(x, y, width, height);
00267 buffer.setRenderWidth(width);
00268 renderStateManager.setHeight(height);
00269 }
00270
00274 @Nullable
00275 @Override
00276 public Dimension getPreferredSize() {
00277 return new Dimension(600, 150);
00278 }
00279
00283 @Nullable
00284 @Override
00285 public Dimension getMinimumSize() {
00286 return new Dimension(100, 10);
00287 }
00288
00289 }