// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// 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 (at your option) 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
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: LinkExtendedLabel.java,v 1.14 2007/04/10 13:51:02 spyromus Exp $
//
package com.salas.bb.utils.uif;
import com.salas.bb.core.GlobalController;
import com.salas.bb.core.GlobalModel;
import com.salas.bb.utils.BrowserLauncher;
import com.salas.bb.utils.Constants;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.event.MouseEvent;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
/**
* Multi-line label which holds the link to somewhere.
*/
public class LinkExtendedLabel extends ExtendedLabel
{
private URL link;
private boolean linkPresent = false;
private Color originalForeground;
/**
* Creates pure link label without link.
*/
public LinkExtendedLabel()
{
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
originalForeground = getForeground();
setDragEnabled(true);
setTransferHandler(new URLTransferHandler());
DragSource ds = new DragSource();
ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, new DragGestureListener()
{
public void dragGestureRecognized(final DragGestureEvent dge)
{
TransferHandler th = getTransferHandler();
th.exportAsDrag(LinkExtendedLabel.this, dge.getTriggerEvent(), DnDConstants.ACTION_COPY);
}
});
}
/**
* Intercepts the call and saves foreground.
*
* @param fg color.
*/
public void setForeground(Color fg)
{
super.setForeground(fg);
originalForeground = fg;
}
/**
* Returns link of current label.
*
* @return URL
*/
public URL getLink()
{
return link;
}
/**
* Binds this label to new link.
*
* @param aLink new link URL.
*/
public void setLink(final URL aLink)
{
this.link = aLink;
linkPresent = ((aLink != null) &&
!(Constants.EMPTY_STRING.equals(aLink.toString().trim())));
String fullLink = aLink != null ? aLink.toString() : null;
setToolTipText(fullLink);
}
/**
* Processes mouse events.
*
* @param e event.
*/
protected void processMouseEvent(MouseEvent e)
{
super.processMouseEvent(e);
switch (e.getID())
{
case MouseEvent.MOUSE_CLICKED:
if (linkPresent && (e.getClickCount() == getTriggerClickCount()) &&
(e.getButton() == MouseEvent.BUTTON1))
{
// If user clicked twice then open the link in browser
doAction();
}
break;
case MouseEvent.MOUSE_ENTERED:
// Change color only if link is present
if (linkPresent)
{
super.setForeground(Color.BLUE);
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
GlobalController.SINGLETON.setStatus(getLink().toString());
}
break;
case MouseEvent.MOUSE_EXITED:
// Change color only if link is present
if (linkPresent)
{
super.setForeground(originalForeground);
this.setCursor(Cursor.getDefaultCursor());
GlobalController.SINGLETON.setStatus(null);
}
break;
}
}
/**
* Performs an action when triggered.
*/
protected void doAction()
{
BrowserLauncher.showDocument(getLink(), GlobalModel.SINGLETON.getUserPreferences().getInternetBrowser());
}
/**
* Returns number of clicks triggering opening the link in bowser.
*
* @return number of clicks.
*/
protected int getTriggerClickCount()
{
return 1;
}
private class URLTransferHandler extends TransferHandler
{
private final DataFlavor FLAVOR_URL = createFlavor("application/x-java-url;class=java.net.URL");
private final DataFlavor FLAVOR_URI_LIST = createFlavor("text/uri-list");
private final DataFlavor FLAVOR_PLAIN = createFlavor("text/plain");
private final java.util.List<DataFlavor> FLAVORS;
public URLTransferHandler()
{
FLAVORS = new ArrayList<DataFlavor>();
if (FLAVOR_URL != null) FLAVORS.add(FLAVOR_URL);
if (FLAVOR_URI_LIST != null) FLAVORS.add(FLAVOR_URI_LIST);
if (FLAVOR_PLAIN != null) FLAVORS.add(FLAVOR_PLAIN);
FLAVORS.add(DataFlavor.stringFlavor);
}
private DataFlavor createFlavor(String mime)
{
DataFlavor f;
try
{
f = new DataFlavor(mime);
} catch (ClassNotFoundException e)
{
f = null;
}
return f;
}
@Override
public int getSourceActions(JComponent c)
{
return DnDConstants.ACTION_COPY;
}
@Override
protected Transferable createTransferable(JComponent c)
{
return new Transferable()
{
public DataFlavor[] getTransferDataFlavors()
{
return FLAVORS.toArray(new DataFlavor[FLAVORS.size()]);
}
public boolean isDataFlavorSupported(DataFlavor flavor)
{
return FLAVORS.contains(flavor);
}
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException
{
Object data;
if (flavor.equals(FLAVOR_URL))
{
data = link;
} else
{
data = new ByteArrayInputStream(link.toString().getBytes());
}
return data;
}
};
}
}
}