Code
private final JEditorPane editor = new JEditorPane();
private final JScrollPane scroll = new JScrollPane(editor);
private final JLabel label = new JLabel() {
private transient MouseInputListener handler;
@Override public void updateUI() {
removeMouseListener(handler);
removeMouseMotionListener(handler);
super.updateUI();
handler = new MiniMapHandler();
addMouseListener(handler);
addMouseMotionListener(handler);
}
@Override public void paintComponent(Graphics g) {
super.paintComponent(g);
Container c = SwingUtilities.getAncestorOfClass(JViewport.class, editor);
if (!(c instanceof JViewport) || editor == null) {
return;
}
JViewport vport = (JViewport) c;
Rectangle vrect = vport.getBounds(); // scroll.getViewportBorderBounds();
Rectangle erect = editor.getBounds();
Rectangle crect = SwingUtilities.calculateInnerArea(this, new Rectangle());
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
double sy = crect.getHeight() / erect.getHeight();
AffineTransform at = AffineTransform.getScaleInstance(1d, sy);
// paint Thumb
Rectangle thumbRect = new Rectangle(vrect);
thumbRect.y = vport.getViewPosition().y;
Rectangle r = at.createTransformedShape(thumbRect).getBounds();
int y = crect.y + r.y;
g2.setColor(THUMB_COLOR);
g2.fillRect(0, y, crect.width, r.height);
g2.setColor(THUMB_COLOR.darker());
g2.drawRect(0, y, crect.width - 1, r.height - 1);
g2.dispose();
}
};
private class MiniMapHandler extends MouseInputAdapter {
@Override public void mousePressed(MouseEvent e) {
processMiniMapMouseEvent(e);
}
@Override public void mouseDragged(MouseEvent e) {
processMiniMapMouseEvent(e);
}
protected final void processMiniMapMouseEvent(MouseEvent e) {
Point pt = e.getPoint();
Component c = (Component) e.getComponent();
BoundedRangeModel m = scroll.getVerticalScrollBar().getModel();
int brm = m.getMaximum() - m.getMinimum();
int iv = (int) (.5 - m.getExtent() * .5 + pt.y * brm / (double) c.getHeight());
m.setValue(iv);
}
}
// ...
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll.getVerticalScrollBar().getModel().addChangeListener(e -> label.repaint());
JPanel pp = new JPanel(new BorderLayout(0, 0));
pp.add(label, BorderLayout.NORTH);
JScrollPane minimap = new JScrollPane(pp);
minimap.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
minimap.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
Box box = Box.createHorizontalBox();
box.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
box.add(Box.createHorizontalGlue());
box.add(button);
JPanel p = new JPanel() {
@Override public boolean isOptimizedDrawingEnabled() {
return false;
}
};
p.setLayout(new BorderLayout(0, 0) {
@Override public void layoutContainer(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int width = parent.getWidth();
int height = parent.getHeight();
int top = insets.top;
int bottom = height - insets.bottom;
int left = insets.left;
int right = width - insets.right;
Component ec = getLayoutComponent(parent, BorderLayout.EAST);
if (Objects.nonNull(ec)) {
Dimension d = ec.getPreferredSize();
JScrollBar vsb = scroll.getVerticalScrollBar();
int vsw = vsb.isVisible() ? vsb.getSize().width : 0;
ec.setBounds(right - d.width - vsw, top, d.width, bottom - top);
}
Component cc = getLayoutComponent(parent, BorderLayout.CENTER);
if (Objects.nonNull(cc)) {
cc.setBounds(left, top, right - left, bottom - top);
}
}
}
});
p.add(minimap, BorderLayout.EAST);
p.add(scroll);
References