/*
* (C) Copyright 2005 Nilo J. Gonzalez
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser Gereral Public Licence as published by the Free
* Software Foundation; either version 2 of the Licence, or (at your opinion) any
* later version.
*
* This library is distributed in the hope that it will be usefull, but WITHOUT ANY
* WARRANTY; without even the implied warranty of merchantability or fitness for a
* particular purpose. See the GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence along
* with this library; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, Ma 02111-1307 USA.
*
* http://www.gnu.org/licenses/lgpl.html (English)
* http://gugs.sindominio.net/gnu-gpl/lgpl-es.html (Espa�ol)
*
*
* Original author: Nilo J. Gonzalez
*/
/**
* Esta clase implementa los menus.
* @author Nilo J. Gonzalez
*/
package com.nilo.plaf.nimrod;
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
public class NimRODPopupMenuUI extends BasicPopupMenuUI {
private static Pantalla pantallas[] = null;
private static Kernel kernel = null;
private BufferedImage fondo = null;
private BufferedImage blurFondo = null;
private MiPL mipl;
private static final int MATRIX = 3;
public static ComponentUI createUI( JComponent c) {
if ( pantallas == null ) {
try {
GraphicsDevice[] gda = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
pantallas = new Pantalla[ gda.length];
// El mundo es una mierda....
NimRODPopupMenuUI dummy = new NimRODPopupMenuUI();
for ( int i = 0; i < gda.length; i++) {
pantallas[i] = dummy.new Pantalla( new Robot( gda[i]), gda[i].getDefaultConfiguration().getBounds());
}
}
catch ( Exception ex) {
ex.printStackTrace();
}
}
if ( kernel == null ) {
float[] elements = new float[MATRIX*MATRIX];
for ( int i = 0; i < elements.length; i++ ) {
elements[i] = .1f;
}
int mid = MATRIX/2+1;
elements[mid*mid] = .2f;
kernel = new Kernel( MATRIX,MATRIX, elements);
}
return new NimRODPopupMenuUI();
}
public void installDefaults() {
super.installDefaults();
popupMenu.setBorder( NimRODBorders.getPopupMenuBorder());
popupMenu.setOpaque( false);
}
public void uninstallDefaults() {
super.uninstallDefaults();
LookAndFeel.installBorder( popupMenu, "PopupMenu.border");
popupMenu.setOpaque( true);
}
public void installListeners() {
super.installListeners();
mipl = new MiPL( popupMenu);
popupMenu.addPopupMenuListener( mipl);
}
public void uninstallListeners() {
super.uninstallListeners();
popupMenu.removePopupMenuListener( mipl);
}
public void update( Graphics g, JComponent c) {
if ( blurFondo != null ) {
g.drawImage( blurFondo, 0, 0, null);
}
if ( NimRODUtils.getMenuOpacity() > 5 ) {
Color cFondo = new Color( c.getBackground().getRed(),
c.getBackground().getGreen(),
c.getBackground().getBlue(),
NimRODUtils.getMenuOpacity());
g.setColor( cFondo);
g.fillRect( 0,0, c.getWidth()-4,c.getHeight()-4);
}
}
/**
* Este metodo esta aqui solo para **MINIMIZAR** el problema de usar la clase ROBOT. Esta clase tiene ciertas
* restricciones de seguridad (a parte de que en el JDK de alguna distro de Linux de esas que van de guays el
* programa nativo que hace el trabajo se instala sin permisos de ejecucion) que obligan a que el jar tenga
* que ir firmado al usarse en applets.
* Este metodo hace la llamada a la clase robot para capturar el fondo, y si salta una excepcion (en realidad
* cualquier cosa pues se captura Throwable), se devuelve una imagen tan transparente como se le pida. Esto
* se cargara el efecto de blur (blurrear algo liso es liso) de los menus, pero al menos habra cierta transparencia
* y pintara una buena sombra si no se firma el applet o se usa una distro chapucera.
* Por cierto, si el menu se sale de la ventana tendra un fondo opaco, y por tanto no habra transparencia y la
* sombra quedara fatal
* @param pop
* @param rect
* @param transparencia
* @return
*/
protected BufferedImage pillaFondo( JPopupMenu pop, Rectangle rect, int transparencia) {
BufferedImage img = null;
try {
Robot robot = null;
for ( int i = 0; i < pantallas.length; i++) {
if ( pantallas[i].rect.contains( rect.x, rect.y)) {
robot = pantallas[i].robot;
rect.x -= pantallas[i].rect.x;
rect.y -= pantallas[i].rect.y;
}
}
// Si llega aqui y ninguna pantalla sirve, robot=null y dara un NullPointerExcption, entrara en el catch y mostrara un
// fondo transparente sin blur igual que en los applets.
img = robot.createScreenCapture( rect);
}
catch ( Throwable ex) {
img = new BufferedImage( rect.width, rect.height, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
g.setColor( NimRODUtils.getColorAlfa( pop.getBackground(), transparencia));
g.fillRect( 0,0, rect.width,rect.height);
g.dispose();
}
return img;
}
public Popup getPopup( JPopupMenu pop, int x, int y) {
Dimension dim = pop.getPreferredSize();
Rectangle rect = new Rectangle( x, y, dim.width, dim.height);
fondo = pillaFondo( pop, rect, 0);
if ( NimRODUtils.getMenuOpacity() > 250 ) {
blurFondo = fondo;
}
else {
Rectangle rectAmp = new Rectangle( x-MATRIX, y-MATRIX, dim.width+2*MATRIX, dim.height+2*MATRIX);
BufferedImage clearFondo = pillaFondo( pop, rectAmp, NimRODUtils.getMenuOpacity());
blurFondo = new BufferedImage( dim.width,dim.height, BufferedImage.TYPE_INT_ARGB);
BufferedImage tempFondo = clearFondo.getSubimage( 0,0, clearFondo.getWidth(),clearFondo.getHeight());
ConvolveOp cop = new ConvolveOp( kernel, ConvolveOp.EDGE_NO_OP, null);
cop.filter( clearFondo, tempFondo); // A ditorsionar
cop.filter( tempFondo, clearFondo); // A ditorsionar, otra vez
cop.filter( clearFondo, tempFondo); // A ditorsionar, y otra mas
Graphics g = blurFondo.getGraphics();
g.drawImage( fondo, 0,0, null);
g.drawImage( tempFondo.getSubimage( MATRIX,MATRIX, dim.width - 5, dim.height - 5),
0,0, null);
}
return super.getPopup( pop, x,y);
}
/////////////////////////////////
private class MiPL implements PopupMenuListener {
JPopupMenu papi;
public MiPL( JPopupMenu pop) {
papi = pop;
}
public void popupMenuWillBecomeInvisible( PopupMenuEvent ev) {
if ( fondo == null ) {
return;
}
Graphics g = papi.getRootPane().getGraphics();
Point p = papi.getLocationOnScreen();
Point r = papi.getRootPane().getLocationOnScreen();
g.drawImage( fondo, p.x - r.x, p.y - r.y, null);
fondo = null;
}
public void popupMenuCanceled( PopupMenuEvent ev) {}
public void popupMenuWillBecomeVisible( PopupMenuEvent ev) {}
}
class Pantalla {
Robot robot;
Rectangle rect;
public Pantalla( Robot rob, Rectangle r) {
robot = rob;
rect = r;
}
}
}