org.netbeans.spi.palette.DragAndDropHandler Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.org/licenses/LICENSE-2.0
*
* 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 org.netbeans.spi.palette;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.io.Reader;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import org.netbeans.modules.palette.DefaultModel;
import org.netbeans.modules.palette.ui.TextImporter;
import org.openide.nodes.Index;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.datatransfer.ExTransferable;
import org.openide.util.datatransfer.PasteType;
/**
* An abstract class implemented by palette clients to implement drag and drop
* of new items into the palette window and to customize the default Transferable
* instance of items being dragged from the palette window to editor area.
*
* Client's can support multiple DataFlavors that may help to enable/disable the drop
* when dragging an item over different editor area parts that allow only certain
* item types to be dropped into them.
*
* @author S. Aubrecht
*/
public abstract class DragAndDropHandler {
private boolean isTextDnDEnabled;
private static DragAndDropHandler defaultHandler;
public DragAndDropHandler() {
this( false );
}
/**
* Subclass this class and use this c'tor with true
parameter to support text drag and drop
* into the palette to create new custom code clips. Subclassed instance must be then provided
* to PaletteFactory
when creating PaletteController
.
* @param textDnDEnabled True to allow text to be dropped into the palette window.
*/
protected DragAndDropHandler( boolean textDnDEnabled ) {
this.isTextDnDEnabled = textDnDEnabled;
}
static DragAndDropHandler getDefault() {
if( null == defaultHandler )
defaultHandler = new DefaultDragAndDropHandler();
return defaultHandler;
}
/**
* Add your own custom DataFlavor as need to suppor drag-over a different
* parts of editor area.
*
* @param t Item's default Transferable.
* @param item Palette item's Lookup.
*
*/
public abstract void customize( ExTransferable t, Lookup item );
/**
* @param targetCategory Lookup of the category under the drop cursor.
* @param flavors Supported DataFlavors.
* @param dndAction Drop action type.
*
* @return True if the given category can accept the item being dragged.
*/
public boolean canDrop( Lookup targetCategory, DataFlavor[] flavors, int dndAction ) {
for( int i=0; i= 0 ) {
//the drop item comes from the targetCategory so let's
//just change the order of items
return moveItem( targetCategory, itemLookup, dropIndex );
}
}
}
}
PasteType paste = categoryNode.getDropType( item, dndAction, dropIndex );
if( null != paste ) {
Node[] itemsBefore = categoryNode.getChildren().getNodes( DefaultModel.canBlock() );
paste.paste();
Node[] itemsAfter = categoryNode.getChildren().getNodes( DefaultModel.canBlock() );
if( itemsAfter.length == itemsBefore.length+1 ) {
int currentIndex = -1;
Node newItem = null;
for( int i=itemsAfter.length-1; i>=0; i-- ) {
newItem = itemsAfter[i];
currentIndex = i;
for( int j=0; j= 0 ) {
if( currentIndex < dropIndex )
dropIndex++;
moveItem( targetCategory, newItem.getLookup(), dropIndex );
}
}
return true;
}
if( isTextDnDEnabled && null != DataFlavor.selectBestTextFlavor(item.getTransferDataFlavors()) ) {
importTextIntoPalette( targetCategory, item, dropIndex );
return false; //return false to retain the original dragged text in its source
}
} catch( IOException ioE ) {
Logger.getLogger( DragAndDropHandler.class.getName() ).log( Level.INFO, null, ioE );
} catch( UnsupportedFlavorException e ) {
Logger.getLogger( DragAndDropHandler.class.getName() ).log( Level.INFO, null, e );
}
return false;
}
/**
* Move palette item to a new position in its current category.
*
* @param category Lookup of the category that contains the dragged item.
* @param itemToMove Lookup of the item that is going to be moved to a new position.
* @param moveToIndex Zero-based index to category's children where the item should move to.
*
* @return True if the move operation was successful.
*/
private boolean moveItem( Lookup category, Lookup itemToMove, int moveToIndex ) {
Node categoryNode = (Node)category.lookup( Node.class );
if( null == categoryNode )
return false;
Node itemNode = (Node)itemToMove.lookup( Node.class );
if( null == itemNode )
return false;
Index order = (Index)categoryNode.getCookie( Index.class );
if( null == order ) {
return false;
}
int sourceIndex = order.indexOf( itemNode );
if( sourceIndex < moveToIndex ) {
moveToIndex--;
}
order.move( sourceIndex, moveToIndex );
return true;
}
/**
* @param paletteRoot Lookup of palette's root node.
* @return True if it is possible to reorder categories by drag and drop operations.
*/
public boolean canReorderCategories( Lookup paletteRoot ) {
Node rootNode = (Node)paletteRoot.lookup( Node.class );
if( null != rootNode ) {
return null != rootNode.getCookie( Index.class );
}
return false;
}
/**
* Move the given category to a new position.
*
* @param category The lookup of category that is being dragged.
* @param moveToIndex Zero-based index to palette's root children Nodes
* where the category should move to.
* @return True if the move operation was successful.
*/
public boolean moveCategory( Lookup category, int moveToIndex ) {
Node categoryNode = (Node)category.lookup( Node.class );
if( null == categoryNode )
return false;
Node rootNode = categoryNode.getParentNode();
if( null == rootNode )
return false;
Index order = (Index)rootNode.getCookie( Index.class );
if( null == order ) {
return false;
}
int sourceIndex = order.indexOf( categoryNode );
if( sourceIndex < moveToIndex ) {
moveToIndex--;
}
order.move( sourceIndex, moveToIndex );
return true;
}
private boolean importTextIntoPalette( Lookup targetCategory, Transferable item, int dropIndex )
throws IOException, UnsupportedFlavorException {
DataFlavor flavor = DataFlavor.selectBestTextFlavor( item.getTransferDataFlavors() );
if( null == flavor )
return false;
String textToImport = extractText( item, flavor );
SwingUtilities.invokeLater( new TextImporter( textToImport, targetCategory, dropIndex ) );
return true;
}
private String extractText( Transferable t, DataFlavor flavor )
throws IOException, UnsupportedFlavorException {
Reader reader = flavor.getReaderForText(t);
if( null == reader )
return null;
StringBuffer res = new StringBuffer();
char[] buffer = new char[4*1024];
int len;
while( (len=reader.read( buffer )) > 0 ) {
res.append(buffer, 0, len);
}
return res.toString();
}
private static final class DefaultDragAndDropHandler extends DragAndDropHandler {
public void customize(ExTransferable t, Lookup item) {
//do nothing
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy