/*
* Jajuk
* Copyright (C) The Jajuk Team
* http://jajuk.info
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package org.jajuk.ui.views;
import ext.FlowScrollPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import org.jajuk.base.Album;
import org.jajuk.base.AlbumComparator;
import org.jajuk.base.AlbumManager;
import org.jajuk.base.Directory;
import org.jajuk.base.Item;
import org.jajuk.base.PropertyMetaInformation;
import org.jajuk.base.Track;
import org.jajuk.base.TrackManager;
import org.jajuk.events.JajukEvent;
import org.jajuk.events.JajukEvents;
import org.jajuk.events.ObservationManager;
import org.jajuk.ui.helpers.DefaultMouseWheelListener;
import org.jajuk.ui.helpers.FontManager;
import org.jajuk.ui.helpers.FontManager.JajukFont;
import org.jajuk.ui.helpers.TwoStepsDisplayable;
import org.jajuk.ui.thumbnails.LocalAlbumThumbnail;
import org.jajuk.ui.thumbnails.ThumbnailManager;
import org.jajuk.ui.widgets.InformationJPanel;
import org.jajuk.ui.widgets.JajukJToolbar;
import org.jajuk.ui.widgets.SteppedComboBox;
import org.jajuk.util.Conf;
import org.jajuk.util.Const;
import org.jajuk.util.Filter;
import org.jajuk.util.IconLoader;
import org.jajuk.util.JajukIcons;
import org.jajuk.util.Messages;
import org.jajuk.util.UtilGUI;
import org.jajuk.util.log.Log;
import org.jdesktop.swingx.JXBusyLabel;
/**
* Catalog view. Displays all default covers by album
* <p>
* Catalog perspectives
*/
public class CatalogView extends ViewAdapter implements ActionListener, TwoStepsDisplayable {
/** Generated serialVersionUID. */
private static final long serialVersionUID = 1L;
// Top control panel
JPanel jpControlTop;
JLabel jlSorter;
SteppedComboBox jcbSorter;
JLabel jlFilter;
SteppedComboBox jcbFilter;
JLabel jlContains;
JTextField jtfValue;
JButton jbPrev;
JButton jbNext;
SteppedComboBox jcbPage;
// Bottom control panel
JPanel jpControlBottom;
JComboBox jcbShowCover;
JSlider jsSize;
FlowScrollPanel jpItems;
JScrollPane jsp;
/** Filter properties. */
List<PropertyMetaInformation> alFilters;
/** Sorter properties. */
List<PropertyMetaInformation> alSorters;
/** Do search panel need a search. */
private boolean bNeedSearch = false;
/** Populating flag. */
private boolean bPopulating = false;
/** Default time in ms before launching a search automatically. */
private static final int WAIT_TIME = 600;
/** Date last key pressed. */
private long lDateTyped;
/** Last selected item. */
private LocalAlbumThumbnail item;
/** Page index. */
private int page = 0;
/** Number of page in current selection. */
int iNbPages = 0;
/** Utility list used by size selector. */
private final List<String> sizes = new ArrayList<String>(10);
/** Thumbs list *. */
private List<LocalAlbumThumbnail> thumbs;
/** Last scrollbar position *. */
private int scrollPosition;
/** Swing Timer to refresh the component. */
private final Timer timerSearch = new Timer(WAIT_TIME, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (bNeedSearch && !bPopulating && (System.currentTimeMillis() - lDateTyped >= WAIT_TIME)) {
// reset paging
page = 0;
populateCatalog();
bNeedSearch = false;
}
}
});
/**
* Gets the selected item.
*
* @return the selected item
*/
public LocalAlbumThumbnail getSelectedItem() {
return item;
}
/*
* (non-Javadoc)
*
* @see org.jajuk.ui.IView#display()
*/
@Override
public void initUI() {
initMetaInformation();
sizes.add(THUMBNAIL_SIZE_50X50);
sizes.add(THUMBNAIL_SIZE_100X100);
sizes.add(THUMBNAIL_SIZE_150X150);
sizes.add(THUMBNAIL_SIZE_200X200);
sizes.add(THUMBNAIL_SIZE_250X250);
sizes.add(THUMBNAIL_SIZE_300X300);
// --Top (most used) control items
jpControlTop = new JPanel();
jlSorter = new JLabel(Messages.getString("Sort") + " ");
jcbSorter = new SteppedComboBox();
jcbSorter.setEditable(false);
// note that a single album can contains tracks with different artists
// or genres, we will show it only one
for (PropertyMetaInformation meta : alSorters) {
jcbSorter.addItem(meta.getHumanName());
}
jcbSorter.setSelectedIndex(Conf.getInt(Const.CONF_THUMBS_SORTER));
jcbSorter.addActionListener(this);
jlFilter = new JLabel(Messages.getString("AbstractTableView.0") + " ");
jlContains = new JLabel(" " + Messages.getString("AbstractTableView.7") + " ");
jcbFilter = new SteppedComboBox();
jcbFilter.setEditable(false);
// note that a single album can contains tracks with different artists
// or genres, we will show it only one
for (PropertyMetaInformation meta : alFilters) {
if (meta == null) { // "any" filter
jcbFilter.addItem(Messages.getString("AbstractTableView.8"));
} else {
jcbFilter.addItem(meta.getHumanName());
}
}
jcbFilter.setSelectedIndex(Conf.getInt(Const.CONF_THUMBS_FILTER));
jcbFilter.addActionListener(this);
jtfValue = new JTextField();
jtfValue.setForeground(new Color(172, 172, 172));
jtfValue.setMargin(new Insets(0, 3, 0, 0));
jtfValue.setFont(FontManager.getInstance().getFont(JajukFont.SEARCHBOX));
jtfValue.addKeyListener(new CatalogViewKeyAdaptor());
JToolBar jtbPage = new JajukJToolbar();
jtbPage.setFloatable(false);
jtbPage.setRollover(true);
jbPrev = new JButton(IconLoader.getIcon(JajukIcons.PLAYER_PREVIOUS_SMALL));
jbPrev.setToolTipText(Messages.getString("CatalogView.12"));
jbPrev.addActionListener(this);
jbNext = new JButton(IconLoader.getIcon(JajukIcons.PLAYER_NEXT_SMALL));
jbNext.setToolTipText(Messages.getString("CatalogView.13"));
jbNext.addActionListener(this);
jcbPage = new SteppedComboBox();
jcbPage.setToolTipText(Messages.getString("CatalogView.14"));
jcbPage.addActionListener(this);
jtbPage.add(jbPrev);
jtbPage.add(jcbPage);
jtbPage.add(jbNext);
jpControlTop.setLayout(new MigLayout("ins 3", "[grow][grow][grow][grow]"));
jpControlTop.add(jlFilter, "split 2");
jpControlTop.add(jcbFilter, "grow");
jpControlTop.add(jlContains, "split 2");
jpControlTop.add(jtfValue, "gapright 40,grow,width 100::");
jpControlTop.add(jlSorter, "split 2");
jpControlTop.add(jcbSorter, "gapright 40,grow");
jpControlTop.add(jtbPage, "gapright 5,grow");
// --Bottom (less used) items
jcbShowCover = new JComboBox();
jcbShowCover.addItem(Messages.getString("CatalogView.21"));
jcbShowCover.addItem(Messages.getString("CatalogView.22"));
jcbShowCover.addItem(Messages.getString("CatalogView.2"));
jcbShowCover.setSelectedIndex(Conf.getInt(Const.CONF_THUMBS_SHOW_COVER));
jcbShowCover.addActionListener(this);
JLabel jlSize = new JLabel(Messages.getString("CatalogView.15"));
jsSize = new JSlider(0, 5);
jsSize.setMajorTickSpacing(1);
jsSize.setMinorTickSpacing(1);
jsSize.setSnapToTicks(true);
jsSize.setPaintTicks(true);
jsSize.addMouseWheelListener(new CatalogViewMouseWheelListener(jsSize));
int index = sizes.indexOf(Conf.getString(Const.CONF_THUMBS_SIZE));
if (index < 0) {
index = 2; // 150x150 if a problem occurs
}
jsSize.setValue(index);
// compute size string for slider tooltip
String sizeToDisplay = "" + (50 + 50 * index) + "x" + "" + (50 + 50 * index);
jsSize.setToolTipText(Messages.getString("CatalogView.4") + " " + sizeToDisplay);
jsSize.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
sliderValueChanged();
}
});
jpControlBottom = new JPanel(new MigLayout("gapx 20"));
jpControlBottom.add(jcbShowCover);
jpControlBottom.add(jlSize, "split 2");
jpControlBottom.add(jsSize);
// Set layout
initLayout();
populateCatalog();
// subscriptions to events
ObservationManager.register(this);
// Show facts
showFacts();
// Start the timers
timerSearch.start();
}
/**
* Inits the meta information.
**/
private void initMetaInformation() {
alFilters = new ArrayList<PropertyMetaInformation>(10);
alFilters.add(null); // All
alFilters.add(TrackManager.getInstance().getMetaInformation(Const.XML_TRACK_GENRE));
alFilters.add(TrackManager.getInstance().getMetaInformation(Const.XML_TRACK_ARTIST));
alFilters.add(TrackManager.getInstance().getMetaInformation(Const.XML_TRACK_ALBUM));
alFilters.add(TrackManager.getInstance().getMetaInformation(Const.XML_YEAR));
// please note: this needs to be kept in-sync with what we do in
// AlbumComparator!
alSorters = new ArrayList<PropertyMetaInformation>(10);
alSorters.add(TrackManager.getInstance().getMetaInformation(Const.XML_TRACK_GENRE));
alSorters.add(TrackManager.getInstance().getMetaInformation(Const.XML_TRACK_ARTIST));
alSorters.add(TrackManager.getInstance().getMetaInformation(Const.XML_TRACK_ALBUM));
alSorters.add(TrackManager.getInstance().getMetaInformation(Const.XML_YEAR));
alSorters.add(TrackManager.getInstance().getMetaInformation(Const.XML_TRACK_DISCOVERY_DATE));
alSorters.add(TrackManager.getInstance().getMetaInformation(Const.XML_TRACK_RATE));
alSorters.add(TrackManager.getInstance().getMetaInformation(Const.XML_TRACK_HITS));
}
/**
* Initialize final layout and add main panels.
*/
private void initLayout() {
// Remove any busy label
if (getComponentCount() > 0) {
removeAll();
}
jpItems = new FlowScrollPanel();
jsp = new JScrollPane(jpItems, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jsp.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 0));
jpItems.setScroller(jsp);
jpItems.setLayout(new FlowLayout(FlowLayout.LEFT));
// global layout
setLayout(new MigLayout("", "[grow]", "[][grow][]"));
add(jpControlTop, "grow,wrap");
add(jsp, "wrap,grow");
add(jpControlBottom, "grow");
revalidate();
repaint();
}
/**
* Reset the catalog view and show a busy label Must be called from the EDT.
*/
private void showBusyLabel() {
if (getComponentCount() > 0) {
removeAll();
}
JXBusyLabel busy = new JXBusyLabel(new Dimension(100, 100));
busy.setBusy(true);
setLayout(new MigLayout("", "[grow]", "[grow]"));
add(busy, "center");
revalidate();
repaint();
}
/**
* Show various information in the information panel.
*/
private void showFacts() {
// display facts in the information panel
// n albums
String sMessage = AlbumManager.getInstance().getElementCount() + " "
+ Messages.getString("CatalogView.16");
int albumsPerPage = Conf.getInt(Const.CONF_CATALOG_PAGE_SIZE);
// n albums / page
if (albumsPerPage > 0) {
sMessage += " - " + albumsPerPage + Messages.getString("CatalogView.17");
}
InformationJPanel.getInstance().setSelection(sMessage);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.events.Observer#getRegistrationKeys()
*/
@Override
public Set<JajukEvents> getRegistrationKeys() {
Set<JajukEvents> eventSubjectSet = new HashSet<JajukEvents>();
eventSubjectSet.add(JajukEvents.DEVICE_REFRESH);
eventSubjectSet.add(JajukEvents.DEVICE_MOUNT);
eventSubjectSet.add(JajukEvents.DEVICE_UNMOUNT);
eventSubjectSet.add(JajukEvents.COVER_DEFAULT_CHANGED);
eventSubjectSet.add(JajukEvents.PARAMETERS_CHANGE);
return eventSubjectSet;
}
/**
* Populate the catalog
* <p>
* Must be called from the EDT.
*/
private void populateCatalog() {
// Prevent unwanted view population requests, do not try to synchronize
// 'this' : too many threads
if (bPopulating) {
Log.debug("Already populating the catalog view");
return;
}
bPopulating = true;
// Store current state
scrollPosition = jsp.getVerticalScrollBar().getValue();
thumbs = new ArrayList<LocalAlbumThumbnail>(100);
// Clear all the view and show a busy label instead
showBusyLabel();
// Show the page
UtilGUI.populate(this);
}
/**
* Compute the catalog page to be displayed.
* <p>
* Do *not* call this from the EDT, can take a while to run
*
* @return the object
*/
@Override
public Object longCall() {
// Every albums
List<Album> albums = null;
// The final album list we will display
List<Album> pageAlbums = new ArrayList<Album>(Conf.getInt(Const.CONF_CATALOG_PAGE_SIZE));
try {
Filter filter = null;
if (jtfValue.getText().length() > 0) {
PropertyMetaInformation meta = alFilters.get(jcbFilter.getSelectedIndex());
filter = new Filter((meta == null) ? null : meta.getName(), jtfValue.getText(), true, false);
}
// filter albums matching tracks
List<Track> alAllTracks = TrackManager.getInstance().getTracks();
alAllTracks = Filter.filterItems(alAllTracks, filter, Track.class);
// keep matching albums
HashSet<Album> hsAlbums = new HashSet<Album>(alAllTracks.size() / 10);
for (Item item : alAllTracks) {
Track track = (Track) item;
Album album = track.getAlbum();
hsAlbums.add(album);
}
// Remove albums with no cover if required
Iterator<Album> itAlbums = hsAlbums.iterator();
while (itAlbums.hasNext()) {
Album album = itAlbums.next();
if (jcbShowCover.getSelectedIndex() == Const.CATALOG_VIEW_COVER_MODE_WITH
&& !album.containsCover()) {
itAlbums.remove();
} else if (jcbShowCover.getSelectedIndex() == Const.CATALOG_VIEW_COVER_MODE_WITHOUT
&& album.containsCover()) {
itAlbums.remove();
}
}
albums = new ArrayList<Album>(hsAlbums);
// sort albums
final int index = jcbSorter.getSelectedIndex();
Collections.sort(albums, new AlbumComparator(index));
// Now process each album
Set<Directory> directories = new HashSet<Directory>(albums.size());
Iterator<Album> it = albums.iterator();
while (it.hasNext()) {
Album album = it.next();
// if hide unmounted tracks is set, continue
if (Conf.getBoolean(Const.CONF_OPTIONS_HIDE_UNMOUNTED)) {
// test if album contains at least one mounted file
List<Track> trackset = TrackManager.getInstance().getAssociatedTracks(album, false);
if (trackset.size() == 0) {
it.remove();
continue;
}
boolean bOK = false;
for (Track track : trackset) {
if (track.getReadyFiles().size() > 0) {
bOK = true;
break;
}
}
if (!bOK) {
it.remove();
continue;
}
}
// Take first track of album (to get detailed
// information)
Track anyTrack = album.getAnyTrack();
if (anyTrack != null) {
// Take the directory of any file of the track
List<org.jajuk.base.File> fileList = anyTrack.getFiles();
if (fileList.size() > 0) {
Directory dir = fileList.get(0).getDirectory();
directories.add(dir);
}
}
}
// Leave if zero match
if (albums.size() == 0) {
return pageAlbums;
}
// Force thumbs build if required, this is the longest task of this worker
// we only keep albums for this page
// computes the number of pages
int iSize = Conf.getInt(Const.CONF_CATALOG_PAGE_SIZE);
if (iSize == 0) {
iNbPages = 1;
} else {
// add one page for trailing items
iNbPages = albums.size() / iSize + ((albums.size() % iSize == 0) ? 0 : 1);
}
// After user changed the number of thumbs on a page, we can be
// out of bounds exception so make sure to reinit the page index in
// this case
if (page > iNbPages - 1) {
page = iNbPages - 1;
}
// Add all items
int max = albums.size(); // upper limit
if (page < (iNbPages - 1)) {
// if last page, take simply to total number of
// items to display
max = (page + 1) * Conf.getInt(Const.CONF_CATALOG_PAGE_SIZE);
}
// Populate each thumb if required (THIS IS LOOOOOONG)
for (int i = page * Conf.getInt(Const.CONF_CATALOG_PAGE_SIZE); i < max; i++) {
Album album = albums.get(i);
pageAlbums.add(album);
ThumbnailManager.refreshThumbnail(album, getSelectedSize());
}
} finally {
// Make sure to reset the populating flag in case of problem
// Note that this flag is reseted here and not in the shortCall() method
// because the shortCall method is not called in case of Exception thrown
// in the longCall() method.
bPopulating = false;
}
return pageAlbums;
}
/**
* Catalog page display (must be called from the EDT).
*
* @param in
*/
@Override
public void shortCall(Object in) {
@SuppressWarnings("unchecked")
List<Album> albums = (List<Album>) in;
if (in == null) {
return;
}
// Populate each thumb if required (this is short because the thumb should have already been built in the long call )
for (Album album : albums) {
final LocalAlbumThumbnail thumb = new LocalAlbumThumbnail(album, getSelectedSize(), true);
thumb.populate();
thumbs.add(thumb);
// restore previous selected item if still set
if (item != null) {
if (((Album) thumb.getItem()).equals(item.getItem())) {
CatalogView.this.item = thumb;
CatalogView.this.item.setSelected(true);
}
}
// Thumb selection mouse listener
thumb.getIcon().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
LocalAlbumThumbnail thumb = (LocalAlbumThumbnail) ((JLabel) e.getSource()).getParent();
// Unselect previous thumb
if (CatalogView.this.item != null && CatalogView.this.item != thumb) {
CatalogView.this.item.setSelected(false);
}
// Select new thumb
thumb.setSelected(true);
CatalogView.this.item = thumb;
}
});
}
// populate page selector
// remove action listener
jcbPage.removeActionListener(CatalogView.this);
jcbPage.removeAllItems(); // void it
for (int i = 0; i < iNbPages; i++) { // add the pages
jcbPage.addItem(Messages.getString("CatalogView.11") + " " + (i + 1) + "/" + iNbPages);
// start at page 1, not 0
}
if (iNbPages > 0) {
jcbPage.setSelectedIndex(page);
jcbPage.addActionListener(CatalogView.this);
}
initLayout();
for (LocalAlbumThumbnail thumb : thumbs) {
jpItems.add(thumb);
}
// The scrollbar must be set after current EDT work to be
// effective,
// so queue it
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
jsp.getVerticalScrollBar().setValue(scrollPosition);
}
});
jtfValue.requestFocusInWindow();
UtilGUI.stopWaiting();
}
/*
* (non-Javadoc)
*
* @see org.jajuk.ui.Observer#update(java.lang.String)
*/
@Override
public void update(JajukEvent event) {
JajukEvents subject = event.getSubject();
if (JajukEvents.DEVICE_REFRESH.equals(subject)
|| JajukEvents.COVER_DEFAULT_CHANGED.equals(subject)
|| JajukEvents.DEVICE_MOUNT.equals(subject) || JajukEvents.DEVICE_UNMOUNT.equals(subject)
|| JajukEvents.PARAMETERS_CHANGE.equals(subject)) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
populateCatalog();
}
});
}
// In all cases, update the facts
showFacts();
}
/*
* (non-Javadoc)
*
* @see org.jajuk.ui.IView#getDesc()
*/
@Override
public String getDesc() {
return Messages.getString("CatalogView.0");
}
/*
* (non-Javadoc)
*
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(final ActionEvent e) {
if (e.getSource() == jcbFilter) {
if (jtfValue.getText().trim().equals("")) {
// no need to refresh
return;
}
bNeedSearch = true;
lDateTyped = System.currentTimeMillis();
Conf.setProperty(Const.CONF_THUMBS_FILTER, Integer.toString(jcbFilter.getSelectedIndex()));
} else if (e.getSource() == jcbSorter) {
bNeedSearch = true;
lDateTyped = System.currentTimeMillis();
Conf.setProperty(Const.CONF_THUMBS_SORTER, Integer.toString(jcbSorter.getSelectedIndex()));
} else if (e.getSource() == jcbShowCover) {
Conf.setProperty(Const.CONF_THUMBS_SHOW_COVER,
Integer.toString(jcbShowCover.getSelectedIndex()));
// Reset page to zero to avoid out of bounds exceptions, when restricting
// the filter, less pages are available
page = 0;
// display thumbs
populateCatalog();
} else if (e.getSource() == jbPrev) {
if (page > 0) {
page--;
} else {
page = iNbPages - 1; // go to last
}
populateCatalog();
} else if (e.getSource() == jbNext) {
if (page < (iNbPages - 1)) {
page++;
} else {
page = 0; // go to first
}
populateCatalog();
} else if (e.getSource() == jcbPage) {
page = jcbPage.getSelectedIndex();
populateCatalog();
} else {
this.item.actionPerformed(e);
}
}
/**
* Gets the selected size.
*
* @return current thumbs size as selected with the combo
*/
private int getSelectedSize() {
return 50 + (50 * jsSize.getValue());
}
/**
* .
*/
private class CatalogViewKeyAdaptor extends KeyAdapter {
/*
* (non-Javadoc)
*
* @see java.awt.event.KeyAdapter#keyReleased(java.awt.event.KeyEvent)
*/
@Override
public void keyReleased(KeyEvent e) {
// Ignore escape press, they can come from popup closing
if (e.getKeyCode() != KeyEvent.VK_ESCAPE) {
bNeedSearch = true;
lDateTyped = System.currentTimeMillis();
}
}
}
/**
* .
*/
private class CatalogViewMouseWheelListener extends DefaultMouseWheelListener {
/**
* Instantiates a new catalog view mouse wheel listener.
*
* @param js
*/
public CatalogViewMouseWheelListener(JSlider js) {
super(js);
}
/*
* (non-Javadoc)
*
* @see
* org.jajuk.ui.helpers.DefaultMouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent
* )
*/
@Override
public void mouseWheelMoved(MouseWheelEvent mwe) {
ChangeListener cl = jsSize.getChangeListeners()[0];
// Remove the concurrent change listener
jsSize.removeChangeListener(cl);
super.mouseWheelMoved(mwe);
sliderValueChanged();
// Add again the change listener
jsSize.addChangeListener(cl);
}
}
/**
* Factorized code for thumb size change.
*/
private void sliderValueChanged() {
// Leave user didn't release the move yet
if (jsSize.getValueIsAdjusting()) {
return;
}
// Store size
Conf.setProperty(Const.CONF_THUMBS_SIZE, sizes.get(jsSize.getValue()));
// display thumbs
populateCatalog();
// Adjust tooltips
// compute size string for slider tooltip
String size = "" + (50 + 50 * jsSize.getValue()) + "x" + "" + (50 + 50 * jsSize.getValue());
jsSize.setToolTipText(Messages.getString("CatalogView.4") + " " + size);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.ui.views.ViewAdapter#cleanup()
*/
@Override
public void cleanup() {
// make sure the timer is not running any more
timerSearch.stop();
// we specifically request the focus for jtfValue, therefore we should make sure that we release
// that focus to let this be destroyed
KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
// call the parent class to do more cleanup if necessary
super.cleanup();
}
}