23 package com.realtime.crossfire.jxclient.gui.list;
35 import java.awt.Adjustable;
36 import java.awt.Dimension;
37 import java.awt.Point;
38 import java.awt.Rectangle;
39 import java.awt.event.MouseEvent;
40 import javax.swing.DefaultListModel;
41 import javax.swing.JList;
42 import javax.swing.JScrollPane;
43 import javax.swing.JViewport;
44 import javax.swing.ListSelectionModel;
45 import javax.swing.ScrollPaneConstants;
46 import javax.swing.border.EmptyBorder;
47 import javax.swing.event.ListSelectionListener;
48 import org.jetbrains.annotations.NotNull;
49 import org.jetbrains.annotations.Nullable;
91 private final DefaultListModel<T>
model =
new DefaultListModel<>();
149 list.setFixedCellWidth(cellWidth);
151 list.setOpaque(
false);
152 list.setFocusable(
false);
153 list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
157 viewport.setScrollMode(JViewport.BLIT_SCROLL_MODE);
161 scrollPane =
new JScrollPane(
null, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
165 scrollPane.setBorder(
new EmptyBorder(0, 0, 0, 0));
176 synchronized (getTreeLock()) {
188 return model.get(index);
196 assert Thread.holdsLock(getTreeLock());
197 model.addElement(element);
198 list.setSize(getWidth(), Integer.MAX_VALUE);
200 if (
model.getSize() == 1) {
213 assert Thread.holdsLock(getTreeLock());
214 final int index =
list.getSelectedIndex();
215 final int oldSize =
model.getSize();
216 if (newSize < oldSize) {
217 for (
int i = newSize; i < oldSize; i++) {
223 model.removeRange(newSize, oldSize-1);
224 list.setSize(getWidth(), Integer.MAX_VALUE);
225 if (index >= newSize && newSize > 0) {
240 synchronized (getTreeLock()) {
243 switch (
list.getLayoutOrientation()) {
244 case JList.HORIZONTAL_WRAP:
249 distance = diffLines+diffElements;
252 final int index =
list.getSelectedIndex();
254 return index == -1 || index+distance <
list.getModel().getSize();
258 return index == -1 || index >= -distance;
270 synchronized (getTreeLock()) {
273 switch (
list.getLayoutOrientation()) {
274 case JList.HORIZONTAL_WRAP:
279 distance = diffLines+diffElements;
282 final int index =
list.getSelectedIndex();
285 newIndex = index == -1 ? 0 : Math.min(index+distance,
list.getModel().getSize()-1);
286 }
else if (distance < 0) {
289 newIndex =
list.getModel().getSize()-1;
291 newIndex = Math.max(index+distance, 0);
294 newIndex = index == -1 ? 0 : index;
307 synchronized (getTreeLock()) {
308 final Adjustable scrollBar =
scrollPane.getVerticalScrollBar();
310 return scrollBar.getValue() < scrollBar.getMaximum()-scrollBar.getVisibleAmount();
314 return scrollBar.getValue() > scrollBar.getMinimum();
326 synchronized (getTreeLock()) {
327 final Adjustable scrollBar =
scrollPane.getVerticalScrollBar();
328 final int value = scrollBar.getValue()+distance*
cellHeight;
329 scrollBar.setValue(value);
330 final int index =
list.getSelectedIndex();
332 final int firstIndex =
list.getFirstVisibleIndex();
333 if (index < firstIndex) {
335 switch (
list.getLayoutOrientation()) {
336 case JList.HORIZONTAL_WRAP:
346 final int lastIndex =
list.getLastVisibleIndex();
347 if (index > lastIndex) {
349 switch (
list.getLayoutOrientation()) {
350 case JList.HORIZONTAL_WRAP:
352 final int newTmpColumn = lastIndex-lastIndex%columns+index%columns;
354 if (newTmpColumn <= lastIndex) {
355 newColumn = newTmpColumn;
357 newColumn = newTmpColumn >= columns ? newTmpColumn-columns : lastIndex;
386 super.mouseClicked(e);
391 super.mouseEntered(e);
399 super.mouseExited(e);
407 super.mousePressed(e);
423 super.mouseDragged(e);
431 super.mouseWheelMoved(wheelRotation);
439 private void doSelect(@NotNull
final MouseEvent e) {
440 synchronized (getTreeLock()) {
453 synchronized (getTreeLock()) {
474 private Rec
getIndex(@NotNull
final MouseEvent e) {
475 final Point point = e.getPoint();
476 final Point location =
list.getLocation();
477 point.translate(-location.x, -location.y);
479 final int index =
list.locationToIndex(point);
484 final Rectangle rectangle =
list.getCellBounds(index, index);
485 if (rectangle ==
null || !rectangle.contains(point)) {
488 rectangle.translate(location.x, location.y);
490 return new Rec(index, rectangle);
498 synchronized (getTreeLock()) {
499 final int newIndex2 = Math.min(Math.max(newIndex, 0),
list.getModel().getSize()-1);
500 final int index =
list.getSelectedIndex();
501 if (newIndex2 == index) {
505 list.setSelectedIndex(newIndex2);
506 if (newIndex2 >= 0) {
507 list.ensureIndexIsVisible(newIndex2);
517 synchronized (getTreeLock()) {
542 if (rectangle ==
null) {
554 return text ==
null ? null :
new TooltipText(text, gui.
getComponent().getX()+getX()+rectangle.x, gui.
getComponent().getY()+getY()+rectangle.y, rectangle.width, rectangle.height);
568 protected abstract String
getTooltip(
final int index);
577 synchronized (getTreeLock()) {
578 list.setLayoutOrientation(layoutOrientation);
579 list.setVisibleRowCount(visibleRowCount);
589 synchronized (getTreeLock()) {
590 return list.getSelectedValue();
595 @SuppressWarnings(
"MethodDoesntCallSuperMethod")
597 return new Dimension(64, 64);
601 @SuppressWarnings(
"MethodDoesntCallSuperMethod")
603 return list.getMinimumSize();
607 @SuppressWarnings(
"MethodDoesntCallSuperMethod")
609 return new Dimension(320, 160);
613 public void setBounds(
final int x,
final int y,
final int width,
final int height) {
614 super.setBounds(x, y, width, height);
622 private static class Rec {