Source Code (Use browser search to find items of interest.)

Class Index

kmahjongg'Editor (./kdegames/kmahjongg/Editor.h:23)

class Editor: public QDialog
{
    Q_OBJECT

public:


    Editor
    (
        QWidget* parent = NULL,
        const char* name = NULL
    );

    virtual ~Editor();



protected slots:
	void topToolbarOption(int w);
        void drawFrameMousePressEvent ( QMouseEvent* );
        void drawFrameMouseMovedEvent ( QMouseEvent *);	

	
protected:
	enum {remove=98, insert=99, move=100};
	void paintEvent( QPaintEvent* pa );
	void setupToolbar();
	void loadBoard(void);
	bool saveBoard(void);
	void newBoard(void);
	void drawBackground(QPixmap *to);
	void drawTiles(QPixmap *to);
	bool testSave(void);
	void transformPointToPosition(const QPoint &, POSITION &, bool align);
	void drawCursor(POSITION &p, bool visible);
	bool canInsert(POSITION &p);
	void statusChanged(void);
	const char *statusText(void);
private:
	int mode;
	int numTiles;
	KToolBar *topToolbar;
	KToolBar *sideToolbar;
        FrameImage * drawFrame;
	Tileset tiles;
	BoardLayout theBoard;
	bool clean;
	POSITION currPos;
	QLabel *theLabel;
private:

};

kmahjongg'Editor::Editor() (./kdegames/kmahjongg/Editor.cpp:48)

Editor::Editor
(
	QWidget* parent,
	const char* name
)
    :
    QDialog( parent, name, TRUE, 0 ), tiles(false)
{

    int sWidth = (BoardLayout::width+2)*(tiles.qWidth());
    int sHeight =( BoardLayout::height+2)*tiles.qHeight();

    sWidth += 4*tiles.shadowSize();

    drawFrame = new FrameImage( this, "drawFrame" ); 
    drawFrame->setGeometry( 10, 40 ,sWidth ,sHeight);
    drawFrame->setMinimumSize( 0, 0 );
    drawFrame->setMaximumSize( 32767, 32767 );
    drawFrame->setFocusPolicy( QWidget::NoFocus );
    drawFrame->setBackgroundMode( QWidget::PaletteBackground );
    drawFrame->setFontPropagation( QWidget::NoChildren );
    drawFrame->setPalettePropagation( QWidget::NoChildren );
    drawFrame->setFrameStyle( 49 );
    drawFrame->setMouseTracking(true);

    resize( sWidth+60, sHeight+60);
    setMinimumSize( sWidth+60, sHeight+60);
    setMaximumSize( sWidth+60, sHeight+60);

   // setup the tool bar
   setupToolbar();

   // load in the tile set
   tiles.loadTileset(preferences.tileset());

   // tell the user what we do
   setCaption(i18n("Edit board layout")); 


   connect( drawFrame, SIGNAL(mousePressed(QMouseEvent *) ),
		SLOT(drawFrameMousePressEvent(QMouseEvent *))); 
   connect( drawFrame, SIGNAL(mouseMoved(QMouseEvent *) ),
		SLOT(drawFrameMouseMovedEvent(QMouseEvent *))); 

   clean= true;
   mode = insert;
   numTiles=0;
   statusChanged();
}




kmahjongg'Editor::~Editor() (./kdegames/kmahjongg/Editor.cpp:100)

Editor::~Editor()
{
}

// ---------------------------------------------------------

kmahjongg'Editor::setupToolbar() (./kdegames/kmahjongg/Editor.cpp:105)

void Editor::setupToolbar()
{

    KIconLoader *loader = KGlobal::iconLoader();
    topToolbar = new KToolBar( this, "editToolBar" );
    KToolBarRadioGroup *radio = new KToolBarRadioGroup(topToolbar);

    // new game
    topToolbar->insertButton(loader->loadIcon("filenew", KIcon::Toolbar),
            ID_TOOL_NEW, TRUE, i18n("New board."));
    // open game
    topToolbar->insertButton(loader->loadIcon("fileopen", KIcon::Toolbar),
            ID_TOOL_LOAD, TRUE, i18n("Open board."));
    // save game
    topToolbar->insertButton(loader->loadIcon("filefloppy", KIcon::Toolbar),
            ID_TOOL_SAVE, TRUE, i18n(" Save board."));

#ifdef FUTURE_OPTIONS
    // Select 
    topToolbar->insertSeparator();
    topToolbar->insertButton(loader->loadIcon("rectangle_select", KIcon::Toolbar),
            ID_TOOL_SELECT, TRUE, i18n("Select."));
    topToolbar->insertButton(loader->loadIcon("editcut", KIcon::Toolbar),
            ID_TOOL_CUT, TRUE, i18n("Cut."));
    topToolbar->insertButton(loader->loadIcon("editcopy", KIcon::Toolbar),
            ID_TOOL_COPY, TRUE, i18n("Copy."));
    topToolbar->insertButton(loader->loadIcon("editpaste", KIcon::Toolbar),
            ID_TOOL_PASTE, TRUE, i18n("Paste."));

    topToolbar->insertSeparator();
    topToolbar->insertButton(loader->loadIcon("move", KIcon::Toolbar),
            ID_TOOL_MOVE, TRUE, i18n("Move tiles."));
#endif
    topToolbar->insertButton(loader->loadIcon("pencil", KIcon::Toolbar),
            ID_TOOL_ADD, TRUE, i18n("Add tiles."));
    topToolbar->insertButton(loader->loadIcon("delete", KIcon::Toolbar),
            ID_TOOL_DEL, TRUE, i18n("Remove tiles."));

    topToolbar->setToggle(ID_TOOL_ADD);
    topToolbar->setToggle(ID_TOOL_MOVE);
    topToolbar->setToggle(ID_TOOL_DEL);
    topToolbar->toggleButton(ID_TOOL_ADD);
    radio->addButton(ID_TOOL_ADD);
    radio->addButton(ID_TOOL_MOVE);
    radio->addButton(ID_TOOL_DEL);

    // board shift

    topToolbar->insertSeparator();
    topToolbar->insertButton(loader->loadIcon("back", KIcon::Toolbar),
            ID_TOOL_LEFT, TRUE, i18n("Shift left."));
    topToolbar->insertButton(loader->loadIcon("up", KIcon::Toolbar),
            ID_TOOL_UP, TRUE, i18n("Shift up."));
    topToolbar->insertButton(loader->loadIcon("down", KIcon::Toolbar),
            ID_TOOL_DOWN, TRUE, i18n("Shift down."));
    topToolbar->insertButton(loader->loadIcon("forward", KIcon::Toolbar),
            ID_TOOL_RIGHT, TRUE, i18n("Shift right."));

    topToolbar->insertSeparator();
    topToolbar->insertButton(loader->loadIcon("exit", KIcon::Toolbar),
            ID_META_EXIT, TRUE, i18n("Exit."));

    // status in the toolbar for now (ick)

    theLabel = new QLabel(statusText(), topToolbar);
    int lWidth = theLabel->sizeHint().width();

    topToolbar->insertWidget(ID_TOOL_STATUS,lWidth, theLabel );
     topToolbar->alignItemRight( ID_TOOL_STATUS, true ); 

    //addToolBar(topToolbar);
   connect( topToolbar,  SIGNAL(clicked(int) ), SLOT( topToolbarOption(int) ) );

    topToolbar->updateRects(0);
     topToolbar->setFullWidth(true);
    topToolbar->setBarPos(KToolBar::Top);
//    topToolbar->enableMoving(false);
    topToolbar->adjustSize();
    setMinimumWidth(topToolbar->width());


}                   


kmahjongg'Editor::statusChanged() (./kdegames/kmahjongg/Editor.cpp:188)

void Editor::statusChanged(void) {
	bool canSave = ((numTiles !=0) && ((numTiles & 1) == 0));
	theLabel->setText(statusText());
 	topToolbar->setItemEnabled( ID_TOOL_SAVE, canSave); 
}



kmahjongg'Editor::topToolbarOption() (./kdegames/kmahjongg/Editor.cpp:195)

void Editor::topToolbarOption(int option) {

    switch(option) {
	case ID_TOOL_NEW:
		newBoard();		
		break;
	case ID_TOOL_LOAD:
		loadBoard();
		break;
	case ID_TOOL_SAVE:
		saveBoard();
		break;
	case ID_TOOL_LEFT:
		theBoard.shiftLeft();
		repaint(false);
	        break;
	case ID_TOOL_RIGHT:
		theBoard.shiftRight();
		repaint(false);
	        break;
	case ID_TOOL_UP:
		theBoard.shiftUp();
		repaint(false);
	        break;
	case ID_TOOL_DOWN:
		theBoard.shiftDown();
		repaint(false);
	        break;
	case ID_TOOL_DEL:
			mode=remove;	
		break;

	case ID_TOOL_MOVE:
			mode=move;	
		break;

	case ID_TOOL_ADD:
			mode = insert;
		break;
	case ID_META_EXIT:
			close();
		break;

	default:

	break;
    }

}


kmahjongg'Editor::statusText() (./kdegames/kmahjongg/Editor.cpp:245)

const char *Editor::statusText(void) {
	static char buff[256];

	int x=currPos.x;
	int y=currPos.y;
	int z= currPos.e;
	
	if (z == 100)
		z = 0;
	else
		z=z+1;

	if (x >=BoardLayout::width || x <0 || y >=BoardLayout::height || y <0)
		x = y = z = 0;

	sprintf(buff, i18n("Tiles: %3.3d Pos: %2.2d,%2.2d,%2.2d"), numTiles,
		x,y,z);
	return buff;
}



kmahjongg'Editor::loadBoard() (./kdegames/kmahjongg/Editor.cpp:266)

void Editor::loadBoard(void) {

    if ( !testSave() )
	return;

    KURL url = KFileDialog::getOpenURL( 
				NULL, 
				"*.layout|Board layout (*.layout)\n"
				"*.*|All files (*.*)", 
				this, 
				i18n("Open board layout." ));

   if ( url.isEmpty() )
        return;


    theBoard.loadBoardLayout( url.path() );

    repaint(false);
}


// Clear out the contents of the board. Repaint the screen
// set values to their defaults.

kmahjongg'Editor::newBoard() (./kdegames/kmahjongg/Editor.cpp:290)

void Editor::newBoard(void) {
    if (!testSave())
	return;



    theBoard.clearBoardLayout();



    clean=true;
    numTiles=0;
    statusChanged();
    repaint(false);
}


kmahjongg'Editor::saveBoard() (./kdegames/kmahjongg/Editor.cpp:306)

bool Editor::saveBoard(void) {
    // get a save file name
    KURL url = KFileDialog::getSaveURL( 
				NULL, 
				"*.layout|Board layout (*.layout)\n"
				"*.*|All files (*.*)", 
				this, 
				i18n("Save board layout." ));
   if( !url.isLocalFile() )
   {
      KMessageBox::sorry( 0L, i18n( "Only saving to local files currently supported." ) );
      return false;
   }
 
   if ( url.isEmpty() )
       return false;

    QFileInfo f( url.path() );
    if ( f.exists() ) {
	// if it already exists, querie the user for replacement
	int res=KMessageBox::warningYesNo(this, 
			i18n("A file with that name "
					   "already exists, do you "
					   "wish to overwrite it?"),
					i18n("Save board layout." ));
	if (res != KMessageBox::Yes) 
		return false;
    }
	
    bool result = theBoard.saveBoardLayout( url.path() );
    if (result==true){
        clean = true;
        return true;
    } else {
	return false;
    }
}


// test if a save is required and return true if the app is to continue
// false if cancel is selected. (if ok then call out to save the board

kmahjongg'Editor::testSave() (./kdegames/kmahjongg/Editor.cpp:347)

bool Editor::testSave(void) 
{

    if (clean)
	return(true);

    int res;
    res=KMessageBox::warningYesNoCancel(this,  
	i18n("The board has been modified, would you" 
		"like to save the changes?"));

    if (res == KMessageBox::Yes) {
	// yes to save
	if (saveBoard()) {
  	    return true;
	} else {
	    KMessageBox::sorry(this, i18n("Save failed. Aborting operation."));	
	}
    } else {
	return (res != KMessageBox::Cancel);
    }
    return(true);
}


// The main paint event, draw in the grid and blit in 
// the tiles as specified by the layout.


kmahjongg'Editor::paintEvent() (./kdegames/kmahjongg/Editor.cpp:375)

void Editor::paintEvent( QPaintEvent*  ) {
    // first we layer on a background grid
    QPixmap buff;
    QPixmap *dest=drawFrame->getPreviewPixmap();
    buff.resize(dest->width(), dest->height()); 
    drawBackground(&buff);
    drawTiles(&buff); 
    bitBlt(dest, 0,0,&buff, 0,0,buff.width(), buff.height(), CopyROP); 

    drawFrame->repaint(false);
}


kmahjongg'Editor::drawBackground() (./kdegames/kmahjongg/Editor.cpp:387)

void Editor::drawBackground(QPixmap *pixmap) {

    QPainter p(pixmap);


    // blast in a white background   
    p.fillRect(0,0,pixmap->width(), pixmap->height(), QColor(white));


    // now put in a grid of tile quater width squares
    int sy = (tiles.height()/2)+tiles.shadowSize();
    int sx = (tiles.width()/2);

    for (int y=0; y<=BoardLayout::height; y++) {
	int nextY=sy+(y*tiles.qHeight());
	p.drawLine(sx, nextY,sx+(BoardLayout::width*tiles.qWidth()), nextY); 
    }

    for (int x=0; x<=BoardLayout::width; x++) {
	int nextX=sx+(x*tiles.qWidth());
	p.drawLine(nextX, sy, nextX, sy+BoardLayout::height*tiles.qHeight()); 
    }


}


kmahjongg'Editor::drawTiles() (./kdegames/kmahjongg/Editor.cpp:413)

void Editor::drawTiles(QPixmap *dest) {

    QPainter p(dest);


    // blast in a white background   
   tiles.loadTileset(preferences.tileset());
   
    int xOffset = tiles.width()/2;
    int yOffset = tiles.height()/2;
    short tile = 0;

    // we iterate over the depth stacking order. zach sucessive level is
    // drawn one indent up and to the right. The indent is the width
    // of the 3d relief on the tile left (tile shadow width)
    for (int z=0; z<BoardLayout::depth; z++) {
        // we draw down the board so the tile below over rights our border
        for (int y = 0; y < BoardLayout::height; y++) {
            // drawing right to left to prevent border overwrite
            for (int x=BoardLayout::width-1; x>=0; x--) {
                int sx = x*(tiles.qWidth()  )+xOffset;
                int sy = y*(tiles.qHeight()  )+yOffset;
                if (theBoard.getBoardData(z, y, x) != '1') {
                    continue;
                }
		QPixmap *t;
		tile=(z*BoardLayout::depth)+
			(y*BoardLayout::height)+
				(x*BoardLayout::width);
//		if (mode==remove && currPos.x==x && currPos.y==y && currPos.e==z) {
//                   t = tiles.selectedPixmaps(44));
//		} else {
                   t = tiles.unselectedPixmaps(43);
//		}

                // Only one compilcation. Since we render top to bottom , left
                // to right situations arise where...:
                // there exists a tile one q height above and to the left
                // in this situation we would draw our top left border over it
                // we simply split the tile draw so the top half is drawn
                // minus border
                if ((x>1) && (y>0) && theBoard.getBoardData(z,y-1,x-2)=='1'){

                    bitBlt( dest,
                            sx+tiles.shadowSize(), sy,
                            t, tiles.shadowSize() ,0,
                            t->width()-tiles.shadowSize(),
                            t->height()/2, CopyROP );


                    bitBlt( dest, sx, sy+t->height()/2,
                        t, 0,t->height()/2,t->width(),t->height()/2,CopyROP);
                } else {

                bitBlt( dest, sx, sy,
                    t, 0,0, t->width(), t->height(), CopyROP );
                }


                tile++;
                tile = tile % 143;
            }
        }
        xOffset +=tiles.shadowSize();
        yOffset -=tiles.shadowSize();
    }                                 
}


// convert mouse position on screen to a tile z y x coord
// different to the one in kmahjongg.cpp since if we hit ground
// we return a result too.


kmahjongg'Editor::transformPointToPosition() (./kdegames/kmahjongg/Editor.cpp:486)

void Editor::transformPointToPosition(
        const QPoint& point,
        POSITION& MouseClickPos,
	bool align) 
{
    short z = 0; // shut the compiler up about maybe uninitialised errors
    short y = 0;
    short x = 0;
    MouseClickPos.e = 100;

    // iterate over z coordinate from top to bottom
    for( z=BoardLayout::depth-1; z>=0; z-- )
    {
        // calculate mouse coordiantes --> position in game board
	// the factor -theTiles.width()/2 must keep track with the 
	// offset for blitting in the print zvent (FIX ME)
        x = ((point.x()-tiles.width()/2)-(z+1)*tiles.shadowSize())/ tiles.qWidth();
        y = ((point.y()-tiles.height()/2)+ z*tiles.shadowSize()) / tiles.qHeight();


        // skip when position is illegal
        if (x<0 || x>=BoardLayout::width || y<0 || y>=BoardLayout::height) 
		continue;

        // 
        switch( theBoard.getBoardData(z,y,x) )
        {
            case (UCHAR)'3':    if (align)
				    x--;y--;
                                break;

            case (UCHAR)'2':    if (align)
				    x--;
                                break;

            case (UCHAR)'4':    if (align)
				    y--;
                                break;

            case (UCHAR)'1':    break;

            default :           continue;
        }
        // if gameboard is empty, skip
        if ( ! theBoard.getBoardData(z,y,x) ) 
		continue;

        // here, position is legal
        MouseClickPos.e = z;
        MouseClickPos.y = y;
        MouseClickPos.x = x;
        MouseClickPos.f = theBoard.getBoardData(z,y,x);
	break;
    }
    if (MouseClickPos.e == 100) {
    	MouseClickPos.x = x;
    	MouseClickPos.y = y;	
    	MouseClickPos.f=0;
    }
}


// we swallow the draw frames mouse clicks and process here

kmahjongg'Editor::drawFrameMousePressEvent() (./kdegames/kmahjongg/Editor.cpp:549)

void Editor::drawFrameMousePressEvent( QMouseEvent* e )
{

	POSITION mPos;
	transformPointToPosition(e->pos(), mPos, (mode == remove));	

	switch (mode) {
		case remove:
		    if (!theBoard.tileAbove(mPos) && mPos.e < BoardLayout::depth && theBoard.isTileAt(mPos) ) {
			theBoard.deleteTile(mPos);
			numTiles--;
			statusChanged();
			drawFrameMouseMovedEvent(e);
			repaint(false);
		    }
		break;
		case insert: {
		    POSITION n = mPos;
		    if (n.e == 100)
			n.e = 0;
		    else
			n.e += 1;
		    if (canInsert(n)) {
			theBoard.insertTile(n);
			numTiles++;
			statusChanged();
			repaint(false);
		    }
		  }
		break;
		default:
		break;
	}

}
 


kmahjongg'Editor::drawCursor() (./kdegames/kmahjongg/Editor.cpp:586)

void Editor::drawCursor(POSITION &p, bool visible)
{
    int x = (tiles.width()/2)+(p.e*tiles.shadowSize())+(p.x * tiles.qWidth());
    int y = (tiles.height()/2)-(p.e*tiles.shadowSize())+(p.y * tiles.qHeight());
    int w = tiles.width();
    int h = tiles.height(); 

    if (p.e==100 || !visible)
	x = -1;
    drawFrame->setRect(x,y,w,h, tiles.shadowSize(), mode-remove);
    drawFrame->repaint(false);    



}



// we swallow the draw frames mouse moves and process here

kmahjongg'Editor::drawFrameMouseMovedEvent() (./kdegames/kmahjongg/Editor.cpp:605)

void Editor::drawFrameMouseMovedEvent( QMouseEvent* e ){


    POSITION mPos;
    transformPointToPosition(e->pos(), mPos, (mode == remove));	
	
    if ((mPos.x==currPos.x) && (mPos.y==currPos.y) && (mPos.e==currPos.e))
	return; 
    currPos = mPos;

    statusChanged();

    switch(mode) {
	case insert:
		POSITION next;
		next = currPos;
		if (next.e == 100)
			next.e = 0;
		else
			next.e += 1;
		
		drawCursor(next, canInsert(next));
	break;

	case remove:
    		drawCursor(currPos, 1);
	break;

	case move:

	break;

    }

}

// can we inser a tile here. We can iff
//	there are tiles in all positions below us (or we are a ground level)
//	there are no tiles intersecting with us on this level
	

kmahjongg'Editor::canInsert() (./kdegames/kmahjongg/Editor.cpp:645)

bool Editor::canInsert(POSITION &p) {


    if (p.e >= BoardLayout::depth)
	return (false);
    if (p.y >BoardLayout::height-2)
	return false;
    if (p.x >BoardLayout::width-2)
	return false;

    POSITION n = p;
    if (p.e != 0) {
	n.e -= 1;
	if (!theBoard.allFilled(n))
	    return(false);	
    }
    return(!theBoard.anyFilled(p));

}