/*
* BufferSwitcher.java - Status bar
* Copyright (C) 2000, 2004 Slava Pestov
*
* 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.gjt.sp.jedit.gui;
//{{{ Imports
import javax.swing.event.*;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.BasicComboBoxUI;
import java.lang.reflect.Field;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import org.gjt.sp.jedit.*;
import org.gjt.sp.jedit.EditBus.EBHandler;
import org.gjt.sp.jedit.bufferset.BufferSet;
import org.gjt.sp.jedit.bufferset.BufferSetManager;
import org.gjt.sp.jedit.msg.PropertiesChanged;
import org.gjt.sp.util.ThreadUtilities;
//}}}
/** BufferSwitcher class
@version $Id: BufferSwitcher.java 23809 2014-12-24 00:44:32Z daleanson $
*/
public class BufferSwitcher extends JComboBox
{
// private members
private final EditPane editPane;
private boolean updating;
// item that was selected before popup menu was opened
private Object itemSelectedBefore;
public static final DataFlavor BufferDataFlavor = new DataFlavor(BufferTransferableData.class, DataFlavor.javaJVMLocalObjectMimeType);
public BufferSwitcher(final EditPane editPane)
{
this.editPane = editPane;
//setFont(new Font("Dialog",Font.BOLD,10));
setTransferHandler(new ComboBoxTransferHandler(this));
setRenderer(new BufferCellRenderer());
setMaximumRowCount(jEdit.getIntegerProperty("bufferSwitcher.maxRowCount", 10));
addPopupMenuListener(new PopupMenuListener()
{
@Override
public void popupMenuWillBecomeVisible(
PopupMenuEvent e)
{
itemSelectedBefore = getSelectedItem();
}
@Override
public void popupMenuWillBecomeInvisible(
PopupMenuEvent e)
{
if (!updating)
{
Buffer buffer = (Buffer)getSelectedItem();
if(buffer != null)
editPane.setBuffer(buffer);
}
editPane.getTextArea().requestFocus();
}
@Override
public void popupMenuCanceled(PopupMenuEvent e)
{
setSelectedItem(itemSelectedBefore);
}
});
EditBus.addToBus(this);
}
public void updateBufferList()
{
// if the buffer count becomes 0, then it is guaranteed to
// become 1 very soon, so don't do anything in that case.
final BufferSet bufferSet = editPane.getBufferSet();
if(bufferSet.size() == 0)
return;
Runnable runnable = new Runnable()
{
@Override
public void run()
{
updating = true;
setMaximumRowCount(jEdit.getIntegerProperty("bufferSwitcher.maxRowCount",10));
Buffer[] buffers = bufferSet.getAllBuffers();
if (jEdit.getBooleanProperty("bufferswitcher.sortBuffers", true)) {
Arrays.sort(buffers, new Comparator<Buffer>(){
public int compare(Buffer a, Buffer b) {
if (jEdit.getBooleanProperty("bufferswitcher.sortByName", true)) {
return a.getName().toLowerCase().compareTo(b.getName().toLowerCase());
} else {
return a.getPath().toLowerCase().compareTo(b.getPath().toLowerCase());
}
}
});
}
setModel(new DefaultComboBoxModel(buffers));
setSelectedItem(editPane.getBuffer());
setToolTipText(editPane.getBuffer().getPath(true));
addDnD();
updating = false;
}
};
ThreadUtilities.runInDispatchThread(runnable);
}
@EBHandler
public void handlePropertiesChanged(PropertiesChanged msg)
{
updateBufferList();
}
static class BufferCellRenderer extends DefaultListCellRenderer
{
@Override
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus)
{
super.getListCellRendererComponent(list,value,index,
isSelected,cellHasFocus);
Buffer buffer = (Buffer)value;
if(buffer == null)
setIcon(null);
else
{
setIcon(buffer.getIcon());
setToolTipText(buffer.getPath());
}
return this;
}
}
private void addDnD()
{
ComboBoxUI ui = getUI();
if (ui instanceof BasicComboBoxUI)
{
try
{
Field listBoxField = getField(ui.getClass(), "listBox");
listBoxField.setAccessible(true);
JList list = (JList)listBoxField.get(ui);
list.setDragEnabled(true);
list.setDropMode(DropMode.INSERT);
list.setTransferHandler(new BufferSwitcherTransferHandler());
}
catch (Exception ignored) // NOPMD
{
// don't do anything if the above fails, it just means dnd won't work.
}
}
}
/**
* Return the named field from the given class.
*/
private Field getField( Class aClass, String fieldName ) throws NoSuchFieldException {
if ( aClass == null )
throw new NoSuchFieldException( "Invalid field : " + fieldName );
try
{
return aClass.getDeclaredField( fieldName );
}
catch ( NoSuchFieldException e )
{
return getField( aClass.getSuperclass(), fieldName );
}
}
private class ComboBoxTransferHandler extends TransferHandler
{
JComboBox comboBox;
public ComboBoxTransferHandler(JComboBox comboBox)
{
this.comboBox = comboBox;
}
public boolean canImport(TransferHandler.TransferSupport info)
{
// we only import Strings
if (!info.isDataFlavorSupported(BufferSwitcher.BufferDataFlavor))
{
return false;
}
if (!comboBox.isPopupVisible())
{
comboBox.showPopup();
}
return false;
}
}
private class BufferSwitcherTransferable implements Transferable
{
private final DataFlavor[] supportedDataFlavor = { BufferSwitcher.BufferDataFlavor };
private final Buffer buffer;
private final JComponent source;
public BufferSwitcherTransferable(Buffer buffer, JComponent source)
{
this.buffer = buffer;
this.source = source;
}
@Override
public DataFlavor[] getTransferDataFlavors()
{
return supportedDataFlavor;
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor)
{
return BufferSwitcher.BufferDataFlavor.equals(flavor);
}
@Override
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException
{
if (!isDataFlavorSupported(flavor))
throw new UnsupportedFlavorException(flavor);
return new BufferTransferableData(buffer, source);
}
}
private class BufferTransferableData
{
private final Buffer buffer;
private final JComponent source;
public BufferTransferableData(Buffer buffer, JComponent source)
{
this.buffer = buffer;
this.source = source;
}
public Buffer getBuffer()
{
return this.buffer;
}
public JComponent getSource()
{
return this.source;
}
}
private class BufferSwitcherTransferHandler extends TransferHandler
{
@Override
public boolean canImport(TransferSupport support)
{
if (!support
.isDataFlavorSupported(BufferSwitcher.BufferDataFlavor))
{
return false;
}
JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
if (dl.getIndex() == -1)
{
return false;
}
Transferable t = support.getTransferable();
BufferTransferableData data;
try
{
data = (BufferTransferableData) t
.getTransferData(BufferSwitcher.BufferDataFlavor);
}
catch (UnsupportedFlavorException e)
{
return false;
}
catch (IOException e)
{
return false;
}
JComponent target = (JComponent) support.getComponent();
EditPane sourceEditPane = (EditPane) GUIUtilities.getComponentParent(
data.getSource(), EditPane.class);
EditPane targetEditPane = (EditPane) GUIUtilities.getComponentParent(
target, EditPane.class);
BufferSet.Scope scope = jEdit.getBufferSetManager().getScope();
View sourceView = sourceEditPane.getView();
View targetView = targetEditPane.getView();
switch (scope)
{
case editpane:
{
return sourceEditPane != targetEditPane;
}
case view:
{
return sourceView != targetView;
}
case global:
return false;
}
return false;
}
@Override
public boolean importData(TransferSupport support)
{
if (!support.isDrop())
{
return false;
}
Transferable t = support.getTransferable();
BufferTransferableData data;
try
{
data = (BufferTransferableData) t
.getTransferData(BufferSwitcher.BufferDataFlavor);
}
catch (UnsupportedFlavorException e)
{
return false;
}
catch (IOException e)
{
return false;
}
JComponent target = (JComponent) support.getComponent();
EditPane targetEditPane = (EditPane) GUIUtilities.getComponentParent(
target, EditPane.class);
Buffer buffer = data.getBuffer();
View view = targetEditPane.getView();
BufferSetManager bufferSetManager = jEdit.getBufferSetManager();
if (buffer != null)
{
bufferSetManager.addBuffer(targetEditPane, buffer);
targetEditPane.setBuffer(buffer);
}
view.toFront();
view.requestFocus();
targetEditPane.requestFocus();
return true;
}
@Override
public int getSourceActions(JComponent c)
{
return COPY_OR_MOVE;
}
@Override
public void exportDone(JComponent c, Transferable t, int action)
{
if (action == MOVE)
{
BufferTransferableData data;
try
{
data = (BufferTransferableData) t
.getTransferData(BufferSwitcher.BufferDataFlavor);
}
catch (UnsupportedFlavorException e)
{
return;
}
catch (IOException e)
{
return;
}
Buffer buffer = data.getBuffer();
EditPane editPane = (EditPane) GUIUtilities.getComponentParent(c,
EditPane.class);
BufferSetManager bufferSetManager = jEdit.getBufferSetManager();
if (buffer != null)
{
bufferSetManager.removeBuffer(editPane, buffer);
}
}
}
@Override
public Transferable createTransferable(JComponent c)
{
JList list = (JList) c;
Buffer buffer = (Buffer) list.getSelectedValue();
if (buffer == null)
{
return null;
}
else
{
return new BufferSwitcherTransferable(buffer, c);
}
}
}
public boolean specialState() {
return isPopupVisible();
}
}
// :noTabs=false: