/***************************************************************************
* $Id: MagWidget.java 274117 2003-12-21 05:47:45Z rdale $
**
* Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
**
* This file is part of an example program for Qt.  This example
* program may be used, distributed and modified without limitation.
**
****************************************************************************/

import org.kde.qt.*;

class MagWidget  extends QWidget
{
private QComboBox   zoom;
private QComboBox   refresh;
private QPushButton saveButton;
private QPushButton multiSaveButton;
private QPushButton quitButton;
private QPixmap	pm;		// pixmap, magnified
private QPixmap	p;		// pixmap
private QImage	image;		// image of pixmap (for RGB)
private QLabel      rgb;
private int		yoffset;	// pixels in addition to the actual picture
private int		z;		// magnification factor
private int		r;		// autorefresh rate (index into refreshrates)
private boolean	grabbing;	// true if qmag is currently grabbing
private int		grabx, graby;
private String	multifn;	// filename for multisave


static String zoomfactors[] = {
    "100%", "200%", "300%", "400%", "500%",
    "600%", "700%", "800%", "1600%" };

static String refreshrates[] = {
    "No autorefresh", "50 per second", "4 per second", "3 per second", "2 per second",
    "Every second", "Every two seconds", "Every three seconds",
    "Every five seconds", "Every ten seconds" };

static int timer[] = {
    0, 20, 250, 333, 500, 1000, 2000, 3000, 5000, 10000 };


MagWidget( )
{
	this(null, null);
}

MagWidget( QWidget parent, String name )
{
    super( parent, name);
    z = 1;			// default zoom (100%)
    r = 0;			// default refresh (none)

    int w=0, x=0, n;

    zoom = new QComboBox( false, this );
    zoom.insertStrList( zoomfactors, 9 );
    connect( zoom, SIGNAL("activated(int)"), SLOT("setZoom(int)") );

    refresh = new QComboBox( false, this );
    refresh.insertStrList( refreshrates, 9 );
    connect( refresh, SIGNAL("activated(int)"), SLOT("setRefresh(int)") );

    for( n=0; n<9; n++) {
	int w2 = zoom.fontMetrics().width( zoomfactors[n] );
	w = w2 > w ? w2 : w;
    }
    zoom.setGeometry( 2, 2, w+30, 20 );

    x = w+34;
    w = 0;
    for( n=0; n<9; n++) {
	int w2 = refresh.fontMetrics().width( refreshrates[n] );
	w = w2 > w ? w2 : w;
    }
    refresh.setGeometry( x, 2, w+30, 20 );

    saveButton = new QPushButton( this );
    connect( saveButton, SIGNAL("clicked()"), this, SLOT("save()") );
    saveButton.setText( "Save" );
    saveButton.setGeometry( x+w+30+2, 2,
			     10+saveButton.fontMetrics().width("Save"), 20 );

    multiSaveButton = new QPushButton( this );
    multiSaveButton.setToggleButton(true);
    connect( multiSaveButton, SIGNAL("clicked()"), this, SLOT("multiSave()") );
    multiSaveButton.setText( "MultiSave" );
    multiSaveButton.setGeometry( saveButton.geometry().right() + 2, 2,
			     10+multiSaveButton.fontMetrics().width("MultiSave"), 20 );

    quitButton = new QPushButton( this );
    connect( quitButton, SIGNAL("clicked()"), qApp(), SLOT("quit()") );
    quitButton.setText( "Quit" );
    quitButton.setGeometry( multiSaveButton.geometry().right() + 2, 2,
			     10+quitButton.fontMetrics().width("Quit"), 20 );

//  #else
//    zoom = null;
//    multiSaveButton = null;

    setRefresh(1);
    setZoom(5);

    rgb = new QLabel( this );
    rgb.setText( "" );
    rgb.setAlignment( AlignVCenter );
    rgb.resize( width(), rgb.fontMetrics().height() + 4 );

    yoffset = zoom.height()	// top buttons
	+ 4			// space around top buttons
	+ rgb.height();	// color-value text height
    setMinimumSize( quitButton.pos().x(), yoffset+20 );
    resize( quitButton.geometry().topRight().x() + 2, yoffset+60 );
//  #else
    yoffset = 0;
    resize(350,350);

    grabx = graby = -1;
    grabbing = false;

    setMouseTracking( true );	// and do let me know what pixel I'm at, eh?

    grabAround( new QPoint(grabx=qApp().desktop().width()/2, graby=qApp().desktop().height()/2) );
}


void setZoom( int index )
{
    if (index == 8)
	z = 16;
    else
	z = index+1;
    grab();
}


void setRefresh( int index )
{
    r = index;
    killTimers();
    if (index != 0 && grabbing)
	startTimer( timer[r] );
}


void save()
{
    if ( p != null ) {
	killTimers();
	String fn = QFileDialog.getSaveFileName();
	if ( !fn.equals("") )
	    p.save( fn, "BMP" );
	if ( r != 0)
	    startTimer( timer[r] );
    }
}

void multiSave()
{
    if ( p != null ) {
	multifn = ""; // stops saving
	multifn = QFileDialog.getSaveFileName();
	if ( multifn.equals("") )
	    multiSaveButton.setOn(false);
	if ( r == 0)
	    p.save( multifn, "BMP" );
    } else {
	multiSaveButton.setOn(false);
    }
}


void grab()
{
    if ( !isVisible() ) 
	return;			// don't eat resources when iconified

    if ( grabx < 0 || graby < 0 )
	return;			// don't grab until the user has said to

    int x,y, w,h;

    w = (width()+z-1)/z;
    h = (height()+z-1-yoffset)/z;
    if ( w<1 || h<1 )
	return;			// don't ask too much from the window system :)

    x = grabx-w/2;		// find a suitable position to grab from
    y = graby-h/2;
    if ( x + w > QApplication.desktop().width() )
	x = QApplication.desktop().width()-w;
    else if ( x < 0 )
	x = 0;
    if ( y + h > QApplication.desktop().height() ) 
	y = QApplication.desktop().height()-h;
    else if ( y < 0 )
	y = 0;

    p = QPixmap.grabWindow( QApplication.desktop().winId(),  x, y, w, h );
    image = p.convertToImage();
    QWMatrix m = new QWMatrix();			// after getting it, scale it
    m.scale( (double)z, (double)z );
    // A cast from Object to QPixmap is needed in java. The xForm methods
    // have several different return types in C++, and must all be of type
    // 'Object' for java
    pm = (QPixmap) p.xForm( m );

    if ( multiSaveButton == null || !multiSaveButton.isOn() )
	repaint( false );		// and finally repaint, flicker-free
}


protected void paintEvent( QPaintEvent e )
{
    if ( pm != null ) {
	QPainter paint = new QPainter( this );
	paint.drawPixmap( 0, zoom != null ? zoom.height()+4 : 0, pm, 
			      0,0, width(), height()-yoffset );
    }
}


protected void mousePressEvent( QMouseEvent e )
{
    if ( !grabbing ) {		// prepare to grab...
	grabbing = true;
	killTimers();
	grabMouse( crossCursor() );
	grabx = -1;
	graby = -1;
    } else {			// REALLY prepare to grab
	grabx = mapToGlobal(e.pos()).x();
	graby = mapToGlobal(e.pos()).y();
    }
}



protected void mouseReleaseEvent( QMouseEvent  e )
{
    if ( grabbing && grabx >= 0 && graby >= 0 ) {
	grabbing = false;
	grabAround(e.pos());
	releaseMouse();
    }
}

void grabAround(QPoint pos)
{
    int rx, ry;
    rx = mapToGlobal(pos).x();
    ry = mapToGlobal(pos).y();
    int w = Math.abs(rx-grabx);
    int h = Math.abs(ry-graby);
    if ( w > 10 && h > 10 ) {
	int pz;
	pz = 1;
	while ( w*pz*h*pz < width()*(height()-yoffset) &&
		w*pz < QApplication.desktop().width() &&
		h*pz < QApplication.desktop().height() )
	    pz++;
	if ( (w*pz*h*pz - width()*(height()-yoffset)) >
	     (width()*(height()-yoffset) - w*(pz-1)*h*(pz-1)) )
	    pz--;
	if ( pz < 1 )
	    pz = 1;
	if ( pz > 8 )
	    pz = 8;
	if ( zoom != null)
	    zoom.setCurrentItem( pz-1 );

	z = pz;
	grabx = (rx < grabx ? rx : grabx) + w/2;
	graby = (ry < graby ? ry : graby) + h/2;
	resize( w*z, h*z+yoffset );
    }
    grab();
    if ( r != 0 )
	startTimer( timer[r] );
}


protected void mouseMoveEvent( QMouseEvent e )
{
    if ( grabbing || pm.isNull() ||
	 e.pos().y() > height() - (zoom != null ? zoom.fontMetrics().height() - 4 : 0) ||
	 e.pos().y() < (zoom != null ? zoom.height()+4 : 4) ) {
	rgb.setText( "" );
    } else {
	int x,y;
	x = e.pos().x() / z;
	y = (e.pos().y() - ( zoom != null ? zoom.height() : 0 ) - 4) / z;
	String pixelinfo = "";
	if ( image.valid(x,y) )
	{
	    int px = image.pixel(x,y);
	    pixelinfo= " " + qRed(px) + "," + qGreen(px) + "," + qBlue(px) + " ";
	    pixelinfo += "#" + Integer.toHexString(qRed(px))
		    + Integer.toHexString(qGreen(px))
			+ Integer.toHexString(qBlue(px)) + " ";
	}
	String label = "x=" + (x+grabx) + ",  y=" + (y+graby) + " " + pixelinfo;
	rgb.setText( label );
    }
}
	

protected void focusOutEvent( QFocusEvent e )
{
    rgb.setText( "" );
}


protected void timerEvent( QTimerEvent e )
{
    grab();
/*
    if ( multiSaveButton.isOn() && !multifn.equals("") ) {
	QRegExp num("[0-9][0-9]");
	int start;
	int len;
	if ((start=num.match(multifn,0,&len))>=0)
	    multifn.replace(num,
		String().setNum(multifn.mid(start,len).toInt()+1)
	    );
	p.save( multifn, "BMP" );
    }
*/
}


protected void resizeEvent( QResizeEvent e )
{
    rgb.setGeometry( 0, height() - rgb.height(), width(), rgb.height() );
    grab();
}




public static void main(String[] args)
{
    QApplication a = new QApplication( args );
    MagWidget m = new MagWidget();
    a.setMainWidget( m );
    m.show();
    a.exec();
    return;
}

	static {
		qtjava.initialize();
	}
}
