You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
474 lines
10 KiB
474 lines
10 KiB
//
|
|
//
|
|
// KBlackBox
|
|
//
|
|
// A simple game inspired by an emacs module
|
|
//
|
|
// File: kbbgfx.cpp
|
|
//
|
|
// The implementation of the KBBGraphic widget
|
|
//
|
|
|
|
#include <tqpainter.h>
|
|
#include <tqpixmap.h>
|
|
#include <tqcolor.h>
|
|
#include <tqkeycode.h>
|
|
#include <tqwmatrix.h>
|
|
|
|
#include "kbbgfx.h"
|
|
#include "util.h"
|
|
|
|
/*
|
|
Constructs a KBBGraphic widget.
|
|
*/
|
|
|
|
KBBGraphic::KBBGraphic( TQPixmap **p, TQWidget* tqparent, const char* name )
|
|
: TQWidget( tqparent, name )
|
|
{
|
|
int i;
|
|
|
|
curRow = curCol = 0;
|
|
setFocusPolicy( TQ_NoFocus );
|
|
setBackgroundColor( gray );
|
|
setCellWidth( CELLW ); // set width of cell in pixels
|
|
setCellHeight( CELLH ); // set height of cell in pixels
|
|
setMouseTracking( FALSE );
|
|
|
|
pix = p;
|
|
if (pix == NULL) pixScaled = NULL;
|
|
else {
|
|
pixScaled = new TQPixmap * [NROFTYPES];
|
|
for (i = 0; i < NROFTYPES; i++) {
|
|
pixScaled[i] = new TQPixmap;
|
|
}
|
|
}
|
|
graphicBoard = NULL;
|
|
drawBuffer = NULL;
|
|
}
|
|
|
|
/*
|
|
Destructor: deallocates memory for contents
|
|
*/
|
|
|
|
KBBGraphic::~KBBGraphic()
|
|
{
|
|
int i;
|
|
|
|
if (pix != NULL) {
|
|
for (i = 0; i < NROFTYPES; i++) {
|
|
delete pix[i];
|
|
}
|
|
delete pix;
|
|
}
|
|
if (pixScaled != NULL) {
|
|
for (i = 0; i < NROFTYPES; i++) {
|
|
delete pixScaled[i];
|
|
}
|
|
delete pixScaled;
|
|
}
|
|
delete graphicBoard;
|
|
delete drawBuffer;
|
|
}
|
|
|
|
/*
|
|
Sets the size of the table
|
|
*/
|
|
|
|
void KBBGraphic::setSize( int w, int h )
|
|
{
|
|
if ((w != numCols) || (h != numRows)) {
|
|
delete graphicBoard;
|
|
graphicBoard = new RectOnArray( w, h );
|
|
graphicBoard->fill( OUTERBBG );
|
|
setNumCols( w );
|
|
setNumRows( h );
|
|
setCellWidth( CELLW );
|
|
setCellHeight( CELLH );
|
|
minW = cellW * numRows;
|
|
minH = cellH * numCols;
|
|
emit(sizeChanged());
|
|
}
|
|
}
|
|
|
|
void KBBGraphic::setCellWidth( int w )
|
|
{
|
|
cellW = w;
|
|
}
|
|
|
|
void KBBGraphic::setCellHeight( int h )
|
|
{
|
|
cellH = h;
|
|
}
|
|
|
|
void KBBGraphic::setNumRows( int rows )
|
|
{
|
|
numRows = rows;
|
|
}
|
|
|
|
void KBBGraphic::setNumCols( int cols )
|
|
{
|
|
numCols = cols;
|
|
}
|
|
|
|
/*
|
|
Scales all pixmaps to desired size.
|
|
*/
|
|
|
|
void KBBGraphic::scalePixmaps( int w, int h )
|
|
{
|
|
int i, w0, h0;
|
|
TQWMatrix wm;
|
|
|
|
w0 = pix[0]->width();
|
|
h0 = pix[0]->height();
|
|
wm.scale( (float) w / (float) w0, (float) h / (float) h0 );
|
|
for (i = 0; i < NROFTYPES; i++) {
|
|
*pixScaled[i] = pix[i]->xForm( wm );
|
|
}
|
|
}
|
|
|
|
/*
|
|
Returns the sizes of the table
|
|
*/
|
|
|
|
int KBBGraphic::numC() { return numCols; }
|
|
int KBBGraphic::numR() { return numRows; }
|
|
int KBBGraphic::width() { return cellW * numRows; }
|
|
int KBBGraphic::height() { return cellH * numCols; }
|
|
int KBBGraphic::wHint() const { return minW; }
|
|
int KBBGraphic::hHint() const { return minH; }
|
|
TQSize KBBGraphic::tqsizeHint() const { return TQSize(wHint(), hHint()); }
|
|
|
|
/*
|
|
Returns a pointer to graphicBoard
|
|
*/
|
|
|
|
RectOnArray *KBBGraphic::getGraphicBoard() { return graphicBoard; }
|
|
|
|
/*
|
|
Handles cell painting for the KBBGraphic widget.
|
|
*/
|
|
|
|
void KBBGraphic::paintCell( TQPainter* p, int row, int col )
|
|
{
|
|
if (pix == NULL) paintCellDefault( p, row, col );
|
|
else paintCellPixmap( p, row, col );
|
|
}
|
|
|
|
void KBBGraphic::paintCellPixmap( TQPainter* p, int row, int col )
|
|
{
|
|
int w = cellW;
|
|
int h = cellH;
|
|
int x2 = w - 1;
|
|
int y2 = h - 1;
|
|
int type;
|
|
TQPixmap pm;
|
|
|
|
// kdDebug(12009) << p->viewport().width() << endl;
|
|
|
|
switch (type = graphicBoard->get( col, row )) {
|
|
case MARK1BBG: pm = *pixScaled[MARK1BBG]; break;
|
|
case OUTERBBG: pm = *pixScaled[OUTERBBG]; break;
|
|
case INNERBBG: pm = *pixScaled[INNERBBG]; break;
|
|
case LASERBBG: pm = *pixScaled[LASERBBG]; break;
|
|
case LFIREBBG: pm = *pixScaled[LFIREBBG]; break;
|
|
case FBALLBBG: pm = *pixScaled[FBALLBBG]; break;
|
|
case TBALLBBG: pm = *pixScaled[TBALLBBG]; break;
|
|
case WBALLBBG: pm = *pixScaled[WBALLBBG]; break;
|
|
default: pm = *pixScaled[OUTERBBG];
|
|
}
|
|
// kdDebug(12009) << pm.width() << " " << w << endl;
|
|
p->drawPixmap( 0, 0, pm );
|
|
// bitBlt( this, col * w, row * h, &pm );
|
|
|
|
p->setPen( black );
|
|
|
|
if (type == INNERBBG) {
|
|
p->drawLine( x2, 0, x2, y2 ); // draw vertical line on right
|
|
p->drawLine( 0, y2, x2, y2 ); // draw horiz. line at bottom
|
|
p->drawLine( 0, 0, x2, 0 );
|
|
p->drawLine( 0, 0, 0, y2 );
|
|
}
|
|
|
|
/*
|
|
Extra drawings for boxes aroud lasers.
|
|
*/
|
|
TQString s;
|
|
switch (type) {
|
|
case RLASERBBG:
|
|
s.sprintf( "%c", 'R' );
|
|
p->drawText( 1, 1, x2-1, y2-1, AlignCenter, s );
|
|
break;
|
|
case HLASERBBG:
|
|
s.sprintf( "%c", 'H' );
|
|
p->drawText( 1, 1, x2-1, y2-1, AlignCenter, s );
|
|
break;
|
|
}
|
|
if (type < 0) {
|
|
s.sprintf( "%d", -type );
|
|
p->drawText( 1, 1, x2-1, y2-1, AlignCenter, s );
|
|
}
|
|
|
|
/*
|
|
Draw extra frame inside if this is the current cell.
|
|
*/
|
|
p->setPen( yellow );
|
|
if ( (row == curRow) && (col == curCol) ) { // if we are on current cell,
|
|
if ( hasFocus() ) {
|
|
p->drawRect( 0, 0, x2, y2 );
|
|
}
|
|
else { // we don't have focus, so
|
|
p->setPen( DotLine ); // use dashed line to
|
|
p->drawRect( 0, 0, x2, y2 );
|
|
p->setPen( SolidLine ); // restore to normal
|
|
}
|
|
}
|
|
}
|
|
|
|
void KBBGraphic::paintCellDefault( TQPainter* p, int row, int col )
|
|
{
|
|
int w = cellW;
|
|
int h = cellH;
|
|
int x2 = w - 1;
|
|
int y2 = h - 1;
|
|
int type;
|
|
TQColor color;
|
|
|
|
switch (type = graphicBoard->get( col, row )) {
|
|
case MARK1BBG: color = darkRed; break;
|
|
case OUTERBBG: color = white; break;
|
|
case INNERBBG: color = gray; break;
|
|
case LASERBBG: color = darkGreen; break;
|
|
case LFIREBBG: color = green; break;
|
|
case FBALLBBG: color = red; break;
|
|
case TBALLBBG: color = blue; break;
|
|
case WBALLBBG: color = cyan; break;
|
|
default: color = white;
|
|
}
|
|
p->fillRect( 0, 0, x2, y2, color );
|
|
|
|
p->setPen( black );
|
|
p->drawLine( x2, 0, x2, y2 ); // draw vertical line on right
|
|
p->drawLine( 0, y2, x2, y2 ); // draw horiz. line at bottom
|
|
|
|
/*
|
|
Extra drawings for boxes aroud lasers.
|
|
*/
|
|
TQString s;
|
|
switch (type) {
|
|
case RLASERBBG:
|
|
s.sprintf( "%c", 'R' );
|
|
p->drawText( 1, 1, x2-1, y2-1, AlignCenter, s );
|
|
break;
|
|
case HLASERBBG:
|
|
s.sprintf( "%c", 'H' );
|
|
p->drawText( 1, 1, x2-1, y2-1, AlignCenter, s );
|
|
break;
|
|
}
|
|
if (type < 0) {
|
|
s.sprintf( "%d", -type );
|
|
p->drawText( 1, 1, x2-1, y2-1, AlignCenter, s );
|
|
}
|
|
|
|
/*
|
|
Draw extra frame inside if this is the current cell.
|
|
*/
|
|
if ( (row == curRow) && (col == curCol) ) { // if we are on current cell,
|
|
if ( hasFocus() ) {
|
|
p->drawEllipse( 1, 1, x2-2, y2-2 ); // draw ellipse
|
|
}
|
|
else { // we don't have focus, so
|
|
p->setPen( DotLine ); // use dashed line to
|
|
p->drawEllipse( 1, 1, x2-2, y2-2 ); // draw ellipse
|
|
p->setPen( SolidLine ); // restore to normal
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Xperimantal...
|
|
*/
|
|
|
|
void KBBGraphic::paintEvent( TQPaintEvent* )
|
|
{
|
|
int i, j;
|
|
TQPainter paint( drawBuffer );
|
|
|
|
// kdDebug(12009) << drawBuffer->width() << endl;
|
|
for (i = 0; i < numRows; i++) {
|
|
for (j = 0; j < numCols; j++) {
|
|
paint.setViewport( j * cellW, i * cellH, width(), height() );
|
|
paintCell( &paint, i, j );
|
|
}
|
|
}
|
|
bitBlt( this, 0, 0, drawBuffer );
|
|
}
|
|
|
|
/*
|
|
Resize event of the KBBGraphic widget.
|
|
*/
|
|
|
|
void KBBGraphic::resizeEvent( TQResizeEvent* )
|
|
{
|
|
int w = TQWidget::width();
|
|
int h = TQWidget::height();
|
|
int wNew, hNew;
|
|
|
|
// kbDebug() << w << " " << h << " " << minW << " " << minH << endl;
|
|
if (w > minW) {
|
|
wNew = w / numC();
|
|
} else {
|
|
wNew = CELLW;
|
|
}
|
|
if (h > minH) {
|
|
hNew = h / numR();
|
|
} else {
|
|
hNew = CELLH;
|
|
}
|
|
if (pix != NULL) scalePixmaps( wNew, hNew );
|
|
setCellWidth( wNew );
|
|
setCellHeight( hNew );
|
|
|
|
delete drawBuffer;
|
|
drawBuffer = new TQPixmap( cellW * numRows, cellH * numCols );
|
|
}
|
|
|
|
/*
|
|
Handles mouse press events for the KBBGraphic widget.
|
|
*/
|
|
void KBBGraphic::mousePressEvent( TQMouseEvent* e )
|
|
{
|
|
if (inputAccepted) {
|
|
/*
|
|
* Middle click finishes the game.
|
|
*/
|
|
if (e->button() == Qt::MidButton) {
|
|
emit endMouseClicked();
|
|
return;
|
|
}
|
|
int oldRow = curRow;
|
|
int oldCol = curCol;
|
|
TQPoint pos = e->pos(); // extract pointer position
|
|
curRow = pos.y() / cellH;
|
|
curCol = pos.x() / cellW;
|
|
//kdDebug(12009) << e->state() << " " << LeftButton << " " << e->state()&LeftButton << endl;
|
|
updateElement( oldCol, oldRow );
|
|
emit inputAt( curCol, curRow, e->button() );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
Handles mouse move events for the KBBGraphic widget.
|
|
*/
|
|
|
|
void KBBGraphic::mouseMoveEvent( TQMouseEvent* e ) {
|
|
if (inputAccepted) {
|
|
int oldRow = curRow;
|
|
int oldCol = curCol;
|
|
TQPoint pos = e->pos(); // extract pointer position
|
|
int movRow = pos.y() / cellH;
|
|
int movCol = pos.x() / cellW;
|
|
// kdDebug(12009) << movRow << " " << curRow << endl;
|
|
if ( (curRow != movRow) // if current cell has moved,
|
|
|| (curCol != movCol) ) {
|
|
curRow = movRow;
|
|
curCol = movCol;
|
|
updateElement( oldCol, oldRow );
|
|
emit inputAt( curCol, curRow, e->state() );
|
|
}
|
|
}
|
|
}
|
|
|
|
void KBBGraphic::slotUp()
|
|
{
|
|
if( curRow > 0 ) {
|
|
moveSelection( -1, 0 );
|
|
}
|
|
}
|
|
|
|
void KBBGraphic::slotDown()
|
|
{
|
|
if( curRow < numRows-1 ) {
|
|
moveSelection( 1, 0 );
|
|
}
|
|
}
|
|
|
|
void KBBGraphic::slotLeft()
|
|
{
|
|
if( curCol > 0 ) {
|
|
moveSelection( 0, -1 );
|
|
}
|
|
}
|
|
|
|
void KBBGraphic::slotRight()
|
|
{
|
|
if( curCol < numCols-1 ) {
|
|
moveSelection( 0, 1 );
|
|
}
|
|
}
|
|
|
|
void KBBGraphic::slotInput()
|
|
{
|
|
if ( !inputAccepted ) {
|
|
return;
|
|
}
|
|
emit inputAt( curCol, curRow, Qt::LeftButton );
|
|
// updateElement( curCol, curRow );
|
|
}
|
|
|
|
void KBBGraphic::moveSelection(int drow, int dcol)
|
|
{
|
|
if ( !dcol && !drow || !inputAccepted ) {
|
|
return;
|
|
}
|
|
curCol += dcol;
|
|
curRow += drow;
|
|
updateElement( curCol - dcol, curRow - drow );
|
|
updateElement( curCol, curRow );
|
|
}
|
|
|
|
/*
|
|
Handles focus reception events for the KBBGraphic widget.
|
|
*/
|
|
|
|
void KBBGraphic::focusInEvent( TQFocusEvent* )
|
|
{
|
|
tqrepaint( FALSE );
|
|
}
|
|
|
|
|
|
/*
|
|
Handles focus loss events for the KBBGraphic widget.
|
|
*/
|
|
|
|
void KBBGraphic::focusOutEvent( TQFocusEvent* )
|
|
{
|
|
tqrepaint( FALSE );
|
|
}
|
|
|
|
/*
|
|
Sets whether user input is processed or not.
|
|
*/
|
|
|
|
void KBBGraphic::setInputAccepted( bool b )
|
|
{
|
|
inputAccepted = b;
|
|
if (b) setFocusPolicy( TQ_StrongFocus );
|
|
else setFocusPolicy( TQ_NoFocus );
|
|
}
|
|
|
|
/*
|
|
Updates the cell at (col,row).
|
|
*/
|
|
|
|
void KBBGraphic::updateElement( int col, int row )
|
|
{
|
|
TQPainter paint( this );
|
|
|
|
paint.setViewport( col * cellW, row * cellH, width(), height() );
|
|
paintCell( &paint, row, col );
|
|
}
|
|
|
|
#include "kbbgfx.moc"
|