/* * Copyright 2004-2010 Information & Software Engineering Group (188/1) * Institute of Software Technology and Interactive Systems * Vienna University of Technology, Austria * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.tuwien.ifs.somtoolbox.apps.viewer.controls; import java.awt.GridBagConstraints; import java.awt.LayoutManager; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Vector; import java.util.logging.Logger; import javax.swing.DefaultListModel; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import at.tuwien.ifs.somtoolbox.apps.viewer.CommonSOMViewerStateData; import at.tuwien.ifs.somtoolbox.apps.viewer.GeneralUnitPNode; import at.tuwien.ifs.somtoolbox.apps.viewer.ItemSelectionListener; import at.tuwien.ifs.somtoolbox.apps.viewer.UnitSelectionListener; import at.tuwien.ifs.somtoolbox.layers.Unit; /** * @author Rudolf Mayer * @version $Id: AbstractSelectionPanel.java 3873 2010-10-28 09:29:58Z frank $ */ public abstract class AbstractSelectionPanel extends AbstractViewerControl implements UnitSelectionListener, ListSelectionListener { private static final long serialVersionUID = 1L; protected ItemSelectionListener itemListener = null; public ItemSelectionListener getItemListener() { return itemListener; } public void setItemListener(ItemSelectionListener itemListener) { this.itemListener = itemListener; } protected DefaultListModel[] playlistmodels; protected JList[] playlists; protected Vector<String>[] absPathVectors; /** * units graphically marked on the map. */ protected Vector<GeneralUnitPNode> markedUnits = new Vector<GeneralUnitPNode>(); /** * units that contribute to the current playlist. */ protected Vector<Unit> unitsInPlaylist = new Vector<Unit>(); protected JScrollPane[] listScrollers; protected int currentSelectionArea = 0; private int selectionAreaCount; protected GeneralUnitPNode[][] selections; public AbstractSelectionPanel(LayoutManager layout, CommonSOMViewerStateData state, String title) { this(layout, state, title, 1); } @SuppressWarnings("unchecked") public AbstractSelectionPanel(LayoutManager layout, CommonSOMViewerStateData state, String title, int selectionAreaCount) { super(title, state, layout); this.selectionAreaCount = selectionAreaCount; playlistmodels = new DefaultListModel[selectionAreaCount]; playlists = new JList[selectionAreaCount]; absPathVectors = new Vector[selectionAreaCount]; selections = new GeneralUnitPNode[selectionAreaCount][]; listScrollers = new JScrollPane[selectionAreaCount]; for (int i = 0; i < selectionAreaCount; i++) { playlistmodels[i] = new DefaultListModel(); playlists[i] = new JList(playlistmodels[i]); playlists[i].setVisibleRowCount(5); absPathVectors[i] = new Vector<String>(); playlists[i].getSelectionModel().addListSelectionListener(this); } } /** * get a String[] containing all objects (absolute paths) in current selection panel * * @return an array of selected objects */ protected Object[] getSelectedSongs() { return getSelectedSongs(currentSelectionArea); } /** * get a String[] containing all objects (absolute paths) in the given selection panel * * @return an array of selected objects */ protected Object[] getSelectedSongs(int selectionArea) { int[] selection = this.playlists[selectionArea].getSelectedIndices(); Object[] oar = new String[selection.length]; for (int i = 0; i < selection.length; i++) { oar[i] = this.absPathVectors[selectionArea].toArray()[selection[i]]; } return oar; } /** * Clears the current playlist and the absPathVectors.<br> * If there are units currently marked on the map, the mark is removed. */ public void clearList() { playlistmodels[currentSelectionArea].removeAllElements(); absPathVectors[currentSelectionArea].removeAllElements(); unitsInPlaylist.clear(); unmarkUnits(); } /** * adds an element to the current playlist and the absPathVectors */ public void addToList(String elementName, Unit u) { addToList(elementName, CommonSOMViewerStateData.fileNamePrefix, u); } /** * adds an element to the current playlist and the absPathVectors * * @param fileNamePrefix an alternative fileNamePrefix */ public void addToList(String elementName, String fileNamePrefix, Unit u) { if (!unitsInPlaylist.contains(u)) { System.out.print("."); unitsInPlaylist.add(u); } playlistmodels[currentSelectionArea].addElement(elementName); absPathVectors[currentSelectionArea].add(fileNamePrefix + elementName + CommonSOMViewerStateData.fileNameSuffix); } /** * graphically marks a unit on the map, and preserves the list of marked units for later clearance */ protected void markUnit(int x, int y) { GeneralUnitPNode unit = state.mapPNode.getUnit(x, y); if (!markedUnits.contains(unit)) { unit.setQueryHit(); markedUnits.add(unit); } } /** * Unmarks all currently marked units on the map.<br> * Which units are marked is determined by the vector <code>markedUnits</code> */ protected void unmarkUnits() { if (!markedUnits.isEmpty()) { for (GeneralUnitPNode unit : markedUnits) { unit.removeQueryHit(); } markedUnits.clear(); } } /** * called whenever the selection has changed, the new selection is added to the JList and to the list of the file's * absolute pathnames */ @Override public void unitSelectionChanged(Object[] selection, boolean newSelection) { // System.out.printf("Abstr.SelPane: unitSelChanged(%d, %b)%n", selection.length, newSelection); if (selectionAreaCount > 1 && newSelection) { currentSelectionArea += 1; if (currentSelectionArea >= selectionAreaCount || currentSelectionArea < 0) { currentSelectionArea = 0; } } if (currentSelectionArea >= 0) { // remove all previously selected files clearList(); } if (selection.length <= 0) { return; } // Angela: make new Array with only GeneralUnitPNodes inside to avoid exceptions when (cluster)labels are shown. ArrayList<Object> tmpSelection = new ArrayList<Object>(); for (Object element : selection) { if (element instanceof GeneralUnitPNode) { tmpSelection.add(element); } } selection = tmpSelection.toArray(); selections[currentSelectionArea] = new GeneralUnitPNode[selection.length]; Vector<Unit> list2 = new Vector<Unit>(); for (int u = 0; u < selection.length; u++) { GeneralUnitPNode gupn = (GeneralUnitPNode) selection[u]; selections[currentSelectionArea][u] = gupn; String[] names = gupn.getMappedDataNames(); // SOMLibDataInformation dataInfo = ((GeneralUnitPNode) selection[u]).getDataInfo(); // TODO: for some reason the ordering of the units gets mixed up. in PlaySOMPlayer it works with this // approach... list2.add(gupn.getUnit()); if (!unitsInPlaylist.contains(gupn.getUnit())) { unitsInPlaylist.add(gupn.getUnit()); } if (names == null) { continue; } for (String element : names) { Object newElement = null; // TODO: ask Robert if UTF-8 decoding is necessary here // Cristoph Becker 20061129: Robert says it does no harm - and I need it. // So I am activating it again ;-) try { // if (dataInfo != null) { // newElement = URLDecoder.decode(dataInfo.getDataDisplayName(names[i]), "UTF-8"); // } else { newElement = URLDecoder.decode(element, "UTF-8"); // } absPathVectors[currentSelectionArea].add(CommonSOMViewerStateData.fileNamePrefix + URLDecoder.decode(element, "UTF-8") + CommonSOMViewerStateData.fileNameSuffix); } catch (UnsupportedEncodingException e) { Logger.getLogger("at.tuwien.ifs.somtoolbox").warning( "Failed to decode string ... adding encoded one"); absPathVectors[currentSelectionArea].add(CommonSOMViewerStateData.fileNamePrefix + element + CommonSOMViewerStateData.fileNameSuffix); newElement = element; } if (!playlistmodels[currentSelectionArea].contains(newElement)) { playlistmodels[currentSelectionArea].addElement(newElement); } } } unitsInPlaylist.retainAll(list2); } protected void addListScrollPanels(GridBagConstraints c) { c.fill = GridBagConstraints.BOTH; c.weightx = 0.5; c.weighty = 1.0; for (int i = 0; i < selectionAreaCount; i++) { listScrollers[i] = new JScrollPane(); listScrollers[i].setViewportView(playlists[i]); getContentPane().add(listScrollers[i], c); } } protected void addSingleListScrollPanel(Object constraints) { listScrollers[0] = new JScrollPane(); listScrollers[0].setViewportView(playlists[0]); getContentPane().add(listScrollers[0], constraints); } @Override public void valueChanged(ListSelectionEvent e) { if (itemListener != null) { itemListener.itemSelected(playlists[0].getSelectedValues()); } } }