* improved scrollpane synchronisation

This commit is contained in:
Reinhard Pointner 2009-05-22 22:28:32 +00:00
parent 73273b8b5b
commit 2963baa889
5 changed files with 102 additions and 89 deletions

View File

@ -32,8 +32,6 @@ public class FileBotList<E> extends JComponent {
protected JScrollPane listScrollPane = new JScrollPane(list);
private String title = null;
public FileBotList() {
setLayout(new BorderLayout());
@ -70,6 +68,11 @@ public class FileBotList<E> extends JComponent {
}
public JScrollPane getListScrollPane() {
return listScrollPane;
}
@Override
public DefaultTransferHandler getTransferHandler() {
return (DefaultTransferHandler) list.getTransferHandler();
@ -100,18 +103,17 @@ public class FileBotList<E> extends JComponent {
public String getTitle() {
return title;
return (String) getClientProperty("title");
}
public void setTitle(String title) {
this.title = title;
putClientProperty("title", title);
if (getBorder() instanceof TitledBorder) {
TitledBorder titledBorder = (TitledBorder) getBorder();
titledBorder.setTitle(title);
TitledBorder border = (TitledBorder) getBorder();
border.setTitle(title);
revalidate();
repaint();
}
}

View File

@ -12,7 +12,6 @@ import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JViewport;
import javax.swing.ListSelectionModel;
import net.miginfocom.swing.MigLayout;
@ -35,8 +34,6 @@ class RenameList<E> extends FileBotList<E> {
list.addMouseListener(dndReorderMouseAdapter);
list.addMouseMotionListener(dndReorderMouseAdapter);
getViewPort().setBackground(list.getBackground());
getRemoveAction().setEnabled(true);
JPanel buttonPanel = new JPanel(new MigLayout("insets 1.2mm, nogrid, fill", "align center"));
@ -46,11 +43,8 @@ class RenameList<E> extends FileBotList<E> {
buttonPanel.add(new JButton(loadAction), "gap 10px");
add(buttonPanel, BorderLayout.SOUTH);
}
public JViewport getViewPort() {
return listScrollPane.getViewport();
listScrollPane.getViewport().setBackground(list.getBackground());
}

View File

@ -91,7 +91,7 @@ public class RenamePanel extends JComponent {
renameModel.useFormatter(File.class, new FileNameFormatter(renameModel.preserveExtension()));
// restore custom episode formatter
renameModel.useFormatter(Episode.class, persistentFormatExpression.getValue());
renameModel.useFormatter(Episode.class, persistentExpressionFormatter.getValue());
RenameListCellRenderer cellrenderer = new RenameListCellRenderer(renameModel);
@ -106,7 +106,7 @@ public class RenamePanel extends JComponent {
filesList.getListComponent().setSelectionModel(selectionModel);
// synchronize viewports
new ViewPortSynchronizer(namesList.getViewPort(), filesList.getViewPort());
new ScrollPaneSynchronizer(namesList, filesList);
// create Match button
JButton matchButton = new JButton(matchAction);
@ -169,7 +169,7 @@ public class RenamePanel extends JComponent {
try {
EpisodeExpressionFormatter formatter = new EpisodeExpressionFormatter(dialog.getExpression());
renameModel.useFormatter(Episode.class, formatter);
persistentFormatExpression.setValue(formatter);
persistentExpressionFormatter.setValue(formatter);
} catch (ScriptException e) {
// will not happen because illegal expressions cannot be approved in dialog
Logger.getLogger("ui").log(Level.WARNING, e.getMessage(), e);
@ -177,7 +177,7 @@ public class RenamePanel extends JComponent {
break;
case USE_DEFAULT:
renameModel.useFormatter(Episode.class, null);
persistentFormatExpression.remove();
persistentExpressionFormatter.remove();
break;
}
}
@ -372,7 +372,7 @@ public class RenamePanel extends JComponent {
}
}
private final PreferencesEntry<EpisodeExpressionFormatter> persistentFormatExpression = Settings.userRoot().entry("rename.format", new AbstractAdapter<EpisodeExpressionFormatter>() {
private final PreferencesEntry<EpisodeExpressionFormatter> persistentExpressionFormatter = Settings.userRoot().entry("rename.format", new AbstractAdapter<EpisodeExpressionFormatter>() {
@Override
public EpisodeExpressionFormatter get(Preferences prefs, String key) {

View File

@ -0,0 +1,86 @@
package net.sourceforge.filebot.ui.panel.rename;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoundedRangeModel;
import javax.swing.Timer;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;
class ScrollPaneSynchronizer {
private final RenameList[] components;
public ScrollPaneSynchronizer(RenameList... components) {
this.components = components;
// share vertical and horizontal scrollbar model
BoundedRangeModel horizontalScrollBarModel = components[0].getListScrollPane().getHorizontalScrollBar().getModel();
BoundedRangeModel verticalScrollBarModel = components[0].getListScrollPane().getVerticalScrollBar().getModel();
// recalculate common size on change
ListEventListener<Object> resizeListener = new ListEventListener<Object>() {
private final Timer timer = new Timer(50, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
syncSize();
// run only once
timer.stop();
}
});
@Override
public void listChanged(ListEvent<Object> evt) {
// sync size when there are no more events coming in
timer.restart();
}
};
// apply to all components
for (RenameList<?> component : components) {
component.getListScrollPane().getHorizontalScrollBar().setModel(horizontalScrollBarModel);
component.getListScrollPane().getVerticalScrollBar().setModel(verticalScrollBarModel);
component.getModel().addListEventListener(resizeListener);
}
}
public void syncSize() {
Dimension max = new Dimension();
for (RenameList component : components) {
// reset preferred size
component.getListComponent().setPreferredSize(null);
// calculate preferred size based on data and renderer
Dimension preferred = component.getListComponent().getPreferredSize();
// update maximum size
if (preferred.width > max.width)
max.width = preferred.width;
if (preferred.height > max.height)
max.height = preferred.height;
}
for (RenameList component : components) {
// set fixed preferred size
component.getListComponent().setPreferredSize(max);
// update scrollbars
component.getListScrollPane().revalidate();
}
}
}

View File

@ -1,69 +0,0 @@
package net.sourceforge.filebot.ui.panel.rename;
import java.awt.Point;
import javax.swing.JViewport;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
class ViewPortSynchronizer {
private final JViewport viewport1;
private final JViewport viewport2;
private final ViewPortSynchronizeListener viewPortSynchronizeListener1;
private final ViewPortSynchronizeListener viewPortSynchronizeListener2;
public ViewPortSynchronizer(JViewport viewport1, JViewport viewport2) {
this.viewport1 = viewport1;
this.viewport2 = viewport2;
viewPortSynchronizeListener1 = new ViewPortSynchronizeListener(viewport2);
viewPortSynchronizeListener2 = new ViewPortSynchronizeListener(viewport1);
setEnabled(true);
}
public void setEnabled(boolean enabled) {
// remove listeners to avoid adding them multiple times
viewport1.removeChangeListener(viewPortSynchronizeListener1);
viewport2.removeChangeListener(viewPortSynchronizeListener2);
// if enabled add them again
if (enabled) {
viewport1.addChangeListener(viewPortSynchronizeListener1);
viewport2.addChangeListener(viewPortSynchronizeListener2);
}
}
private static class ViewPortSynchronizeListener implements ChangeListener {
private final JViewport target;
public ViewPortSynchronizeListener(JViewport target) {
this.target = target;
}
@Override
public void stateChanged(ChangeEvent e) {
JViewport source = (JViewport) e.getSource();
Point viewPosition = source.getViewPosition();
// return if both viewports have the same view position
if (!viewPosition.equals(target.getViewPosition())) {
target.setViewPosition(viewPosition);
target.repaint();
}
}
}
}