I tried to implement a custom List supporting multi line labels as entries.
It works fine - except for the scrolling behaviour of the ScrollPane.
Any time I am pressing the up or down key, the scrollbar is moving down one pixel; eventhough I override the processEvent(AWTEvent) AND processKeyEvent(KeyEvent) methods - in which both I called the KeyEvent.consume() method to avoid this events usual behaviour.
Setting the scroll step to 0:
<code>getVAdjustable().setUnitIncrement(0);
getHAdjustable().setUnitIncrement(0);</code>
shows no effect as it shows no effect to set it to a different value - say 10 or so.
Disable the ScrollPane isnt the solution: it will not receive any keyevents anymore.
So thats the situation and here comes the question: How can I avoid this 1px scrolling, or how can i set a different value (say 0 :).
sourcecode:
<code>
package de.condat.mobileservice.gui;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.ScrollPane;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.util.Vector;
/**
* A list containing zero or more selectable MultiLineLabels. Exactly one or
* zero MultiLineLabel is selected at any time.<br>
* <br>
* This component is written for one purpose only: to extend the functionality
* of the java.awt.List to support multi line entries. No multiple selections
* are supported.
*
* @author pha
*
*/
public class MultiLineList extends ScrollPane {
private Panel innerPanel = new Panel(new VerticalListLayout());
/**
* Constructs an empty MultiLineList.
*/
public MultiLineList() {
super(ScrollPane.SCROLLBARS_AS_NEEDED);
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
getVAdjustable().setUnitIncrement(0);
getHAdjustable().setUnitIncrement(0);
add(innerPanel);
innerPanel.setBackground(Color.white);
}
public void add(String item) {
MultiLineLabel label = new MultiLineLabel(item);
label.setAlignment(Label.LEFT);
innerPanel.add(label);
innerPanel.validate();
innerPanel.repaint();
}
/**
* Adds an item.
*
* @param item
* @deprecated Legacy, use add(String) instead.
*/
public void addItem(String item) {
add(item);
}
/**
* Returns the value of the item at index.
*
* @param index
* The index.
* @return The value of the item.
*/
public String getItem(int index) {
SelectableTextItem[] selectables = getSelectableItems();
return selectables[index].getText();
}
private SelectableTextItem[] getSelectableItems() {
Vector selectables = new Vector();
Component[] components = innerPanel.getComponents();
for (int i = 0; i < components.length; i++) {
if (components[i] instanceof SelectableTextItem) {
selectables.addElement(components[i]);
}
}
SelectableTextItem[] selectableComponents = new SelectableTextItem[selectables
.size()];
selectables.copyInto(selectableComponents);
return selectableComponents;
}
/**
* Returns the index of the selected element or -1 if no element is
* selected.
*/
public int getSelectedIndex() {
SelectableTextItem[] selectables = getSelectableItems();
for (int i = 0; i < selectables.length; i++) {
if (selectables[i].getState()) {
return i;
}
}
return -1;
}
/**
* Returns the value of the selected element or null.
*
* @return The value or null.
*/
public String getSelectedItem() {
SelectableTextItem[] selectables = getSelectableItems();
for (int i = 0; i < selectables.length; i++) {
if (selectables[i].getState()) {
return selectables[i].getText();
}
}
return null;
}
public boolean isFocusTraversable() {
return true;
}
private boolean isVisible(SelectableTextItem item) {
Rectangle bounds = item.getBounds();
Point scrollPosition = getScrollPosition();
return scrollPosition.y <= bounds.y
&& scrollPosition.y + getViewportSize().height >= bounds.y
+ bounds.height;
}
/**
* Moves the specified element to the visible area, if element isnt visible.
*
* @param index
* The element index to make visible.
*/
public void makeVisible(int index) {
SelectableTextItem visible = getSelectableItems()[index];
if (!isVisible(visible)) {
System.out.println("set scroll position");
setScrollPosition(visible.getLocation());
}
}
public void update(Graphics g) {
System.out.println("update");
super.update(g);
System.out.println("update2");
}
public void paint(Graphics g) {
System.out.println("paint");
super.paint(g);
System.out.println("paint2");
}
public void paintAll(Graphics g) {
System.out.println("paintall");
super.paintAll(g);
System.out.println("paintall2");
}
// doesnt catches the adjustmentevents
// protected void processEvent(AWTEvent e) {
// int id = e.getID();
// if ((id & AWTEvent.KEY_EVENT_MASK) == 0) {
// ((KeyEvent) e).consume();
// }
// }
protected void processFocusEvent(FocusEvent fe) {
super.processFocusEvent(fe);
if (fe.getID() == FocusEvent.FOCUS_GAINED) {
if (getSelectedIndex() == -1) {
select(0);
}
}
}
protected void processKeyEvent(KeyEvent ke) {
if (ke.getID() == KeyEvent.KEY_PRESSED) {
int keyCode = ke.getKeyCode();
int select = getSelectedIndex();
if (keyCode == KeyEvent.VK_UP) {
select--;
} else if (keyCode == KeyEvent.VK_DOWN) {
select++;
}
select = Math.max(
Math.min(select, getSelectableItems().length - 1), 0);
select(select);
makeVisible(select);
}
ke.consume();
}
/**
* Removes all items.
*/
public void removeAll() {
innerPanel.removeAll();
}
/**
* Replaces the item at the specified position with the specified item.
*
* @param item
* The new item.
* @param index
* The position of the element to be replaced.
*/
public void replaceItem(String item, int index) {
Component[] components = innerPanel.getComponents();
int count = 0;
for (int i = 0; i < components.length; i++) {
if (components[i] instanceof SelectableTextItem) {
if (count == index) {
innerPanel.remove(i);
MultiLineLabel label = new MultiLineLabel(item);
label.setAlignment(Label.LEFT);
innerPanel.add(label, i);
}
count++;
}
}
}
/**
* Selects the list entry with index = <code>index</code>. If index<0
* all items will be deselected, if index>listentries.length the last valid
* index will be selected.
*
* @param index
* The index to select.
*/
public void select(int index) {
SelectableTextItem[] selectables = getSelectableItems();
if (selectables.length < 1) {
return;
}
if (index < 0) {
for (int i = 0; i < selectables.length; i++) {
selectables[i].setState(false);
}
} else {
int selected = getSelectedIndex();
if (selected != index) {
index = Math.min(index, Math.max(selectables.length - 1, 0));
if (selected > -1) {
selectables[getSelectedIndex()].setState(false);
}
selectables[index].setState(true);
}
}
}
}
</code>



