1 | /* Copyright (C) 1997 Mathias Mueller <in5y158@public.uni-hamburg.de> |
2 | * Copyright (C) 2006 Mauricio Piacentini <mauricio@tabuleiro.com> |
3 | * |
4 | * Kmahjongg is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ |
17 | |
18 | #include "Editor.h" |
19 | #include "prefs.h" |
20 | |
21 | #include <QLabel> |
22 | #include <qevent.h> |
23 | #include <qpainter.h> |
24 | #include <QHBoxLayout> |
25 | #include <QGridLayout> |
26 | |
27 | #include <kmessagebox.h> |
28 | #include <kcomponentdata.h> |
29 | #include <klocale.h> |
30 | #include <kstandarddirs.h> |
31 | #include <kaction.h> |
32 | #include <kactioncollection.h> |
33 | #include <ktoggleaction.h> |
34 | #include <kstandardaction.h> |
35 | #include <kicon.h> |
36 | |
37 | |
38 | Editor::Editor(QWidget *parent) |
39 | : KDialog( parent ), |
40 | tiles() |
41 | { |
42 | setModal(true); |
43 | clean = true; |
44 | numTiles = 0; |
45 | mode = insert; |
46 | |
47 | QWidget *mainWidget = new QWidget(this); |
48 | setMainWidget(mainWidget); |
49 | |
50 | QGridLayout *gridLayout = new QGridLayout(mainWidget); |
51 | QVBoxLayout *layout = new QVBoxLayout(); |
52 | |
53 | // setup the tool bar |
54 | setupToolbar(); |
55 | layout->addWidget(topToolbar); |
56 | |
57 | drawFrame = new FrameImage(this, QSize(0, 0)); |
58 | drawFrame->setFocusPolicy(Qt::NoFocus); |
59 | drawFrame->setMouseTracking(true); |
60 | |
61 | layout->addWidget(drawFrame); |
62 | gridLayout->addLayout(layout, 0, 0, 1, 1); |
63 | |
64 | //toolbar will set our minimum height |
65 | setMinimumHeight(120); |
66 | |
67 | // tell the user what we do |
68 | setCaption(i18n("Edit Board Layout" )); |
69 | |
70 | connect(drawFrame, SIGNAL(mousePressed(QMouseEvent*)), this, SLOT( |
71 | drawFrameMousePressEvent(QMouseEvent*))); |
72 | connect(drawFrame, SIGNAL(mouseMoved(QMouseEvent*)), this, SLOT( |
73 | drawFrameMouseMovedEvent(QMouseEvent*))); |
74 | |
75 | statusChanged(); |
76 | |
77 | setButtons(KDialog::None); |
78 | |
79 | update(); |
80 | } |
81 | |
82 | Editor::~Editor() |
83 | { |
84 | } |
85 | |
86 | void Editor::setTileset(const QString tileset) |
87 | { |
88 | // Exit if the tileset is already set. |
89 | if (tileset == mTileset) { |
90 | return; |
91 | } |
92 | |
93 | // Try to load the new tileset. |
94 | if (!tiles.loadTileset(tileset)) { |
95 | // Try to load the old one. |
96 | if (!tiles.loadTileset(mTileset)) { |
97 | tiles.loadDefault(); |
98 | } |
99 | } else { |
100 | // If loading the new tileset was ok, set the new tileset name. |
101 | mTileset = tileset; |
102 | } |
103 | |
104 | // Must be called to load the graphics and its informations. |
105 | tiles.loadGraphics(); |
106 | |
107 | updateTileSize(size()); |
108 | } |
109 | |
110 | const QString Editor::getTileset() const |
111 | { |
112 | return mTileset; |
113 | } |
114 | |
115 | void Editor::updateTileSize(const QSize size) |
116 | { |
117 | QSize tileSize = tiles.preferredTileSize(size, theBoard.m_width / 2, theBoard.m_height / 2); |
118 | tiles.reloadTileset(tileSize); |
119 | |
120 | borderLeft = (drawFrame->size().width() - (theBoard.m_width * tiles.qWidth())) / 2; |
121 | borderTop = (drawFrame->size().height() - (theBoard.m_height * tiles.qHeight())) / 2; |
122 | } |
123 | |
124 | void Editor::resizeEvent(QResizeEvent *event) |
125 | { |
126 | updateTileSize(event->size()); |
127 | } |
128 | |
129 | void Editor::setupToolbar() |
130 | { |
131 | topToolbar = new KToolBar(this, "editToolBar" ); |
132 | topToolbar->setToolButtonStyle(Qt::ToolButtonIconOnly); |
133 | |
134 | actionCollection = new KActionCollection(this); |
135 | |
136 | // new game |
137 | QAction *newBoard = actionCollection->addAction(QLatin1String("new_board" )); |
138 | newBoard->setIcon(KIcon(QLatin1String("document-new" ))); |
139 | newBoard->setText(i18n("New board" )); |
140 | connect(newBoard, SIGNAL(triggered(bool)), SLOT(newBoard())); |
141 | topToolbar->addAction(newBoard); |
142 | |
143 | // open game |
144 | QAction *openBoard = actionCollection->addAction(QLatin1String("open_board" )); |
145 | openBoard->setIcon(KIcon(QLatin1String("document-open" ))); |
146 | openBoard->setText(i18n("Open board" )); |
147 | connect(openBoard, SIGNAL(triggered(bool)), SLOT(loadBoard())); |
148 | topToolbar->addAction(openBoard); |
149 | |
150 | // save game |
151 | QAction *saveBoard = actionCollection->addAction(QLatin1String("save_board" )); |
152 | saveBoard->setIcon(KIcon(QLatin1String("document-save" ))); |
153 | saveBoard->setText(i18n("Save board" )); |
154 | connect(saveBoard, SIGNAL(triggered(bool)), SLOT(saveBoard())); |
155 | topToolbar->addAction(saveBoard); |
156 | // NOTE dimsuz: how to port this? is it even needed? |
157 | //topToolbar->setButtonIconSet(ID_TOOL_SAVE,loader->loadIconSet("document-save", KIconLoader::Toolbar)); |
158 | |
159 | topToolbar->addSeparator(); |
160 | |
161 | |
162 | #ifdef FUTURE_OPTIONS |
163 | |
164 | |
165 | // Select |
166 | QAction *select = actionCollection->addAction(QLatin1String("select" )); |
167 | select->setIcon(KIcon(QLatin1String("rectangle_select" ))); |
168 | select->setText(i18n("Select" )); |
169 | topToolbar->addAction(select); |
170 | |
171 | // NOTE: use kstandarddactions? |
172 | QAction *cut = actionCollection->addAction(QLatin1String("edit_cut" )); |
173 | cut->setIcon(KIcon(QLatin1String("edit-cut" ))); |
174 | cut->setText(i18n("Cut" )); |
175 | topToolbar->addAction(cut); |
176 | |
177 | QAction *copy = actionCollection->addAction(QLatin1String("edit_copy" )); |
178 | copy->setIcon(KIcon(QLatin1String("edit-copy" ))); |
179 | copy->setText(i18n("Copy" )); |
180 | topToolbar->addAction(copy); |
181 | |
182 | QAction *paste = actionCollection->addAction(QLatin1String("edit_paste" )); |
183 | paste->setIcon(KIcon(QLatin1String("edit-paste" ))); |
184 | paste->setText(i18n("Paste" )); |
185 | topToolbar->addAction(paste); |
186 | |
187 | topToolbar->addSeparator(); |
188 | |
189 | QAction *moveTiles = actionCollection->addAction(QLatin1String("move_tiles" )); |
190 | moveTiles->setIcon(KIcon(QLatin1String("move" ))); |
191 | moveTiles->setText(i18n("Move tiles" )); |
192 | topToolbar->addAction(moveTiles); |
193 | |
194 | |
195 | #endif |
196 | |
197 | |
198 | KToggleAction *addTiles = new KToggleAction(KIcon(QLatin1String("draw-freehand" )), i18n("Add ti" |
199 | "les" ), this); |
200 | actionCollection->addAction(QLatin1String("add_tiles" ), addTiles); |
201 | topToolbar->addAction(addTiles); |
202 | KToggleAction *delTiles = new KToggleAction(KIcon(QLatin1String("edit-delete" )), i18n("Remove t" |
203 | "iles" ), this); |
204 | actionCollection->addAction(QLatin1String("del_tiles" ), delTiles); |
205 | topToolbar->addAction(delTiles); |
206 | |
207 | QActionGroup *radioGrp = new QActionGroup(this); |
208 | radioGrp->setExclusive(true); |
209 | radioGrp->addAction(addTiles); |
210 | addTiles->setChecked(true); |
211 | |
212 | |
213 | #ifdef FUTURE_OPTIONS |
214 | |
215 | |
216 | radioGrp->addAction(moveTiles); |
217 | |
218 | |
219 | #endif |
220 | |
221 | |
222 | radioGrp->addAction(delTiles); |
223 | connect(radioGrp, SIGNAL(triggered(QAction*)), SLOT(slotModeChanged(QAction*))); |
224 | |
225 | // board shift |
226 | |
227 | topToolbar->addSeparator(); |
228 | |
229 | // NOTE: maybe join shiftActions in QActionGroup and create one slot(QAction*) instead of 4 slots? ;) |
230 | // Does this makes sense? dimsuz |
231 | QAction *shiftLeft = actionCollection->addAction(QLatin1String("shift_left" )); |
232 | shiftLeft->setIcon(KIcon(QLatin1String("go-previous" ))); |
233 | shiftLeft->setText(i18n("Shift left" )); |
234 | connect(shiftLeft, SIGNAL(triggered(bool)), SLOT(slotShiftLeft())); |
235 | topToolbar->addAction(shiftLeft); |
236 | |
237 | QAction *shiftUp = actionCollection->addAction(QLatin1String("shift_up" )); |
238 | shiftUp->setIcon(KIcon(QLatin1String("go-up" ))); |
239 | shiftUp->setText(i18n("Shift up" )); |
240 | connect(shiftUp, SIGNAL(triggered(bool)), SLOT(slotShiftUp())); |
241 | topToolbar->addAction(shiftUp); |
242 | |
243 | QAction *shiftDown = actionCollection->addAction(QLatin1String("shift_down" )); |
244 | shiftDown->setIcon(KIcon(QLatin1String("go-down" ))); |
245 | shiftDown->setText(i18n("Shift down" )); |
246 | connect(shiftDown, SIGNAL(triggered(bool)), SLOT(slotShiftDown())); |
247 | topToolbar->addAction(shiftDown); |
248 | |
249 | QAction *shiftRight = actionCollection->addAction(QLatin1String("shift_right" )); |
250 | shiftRight->setIcon(KIcon(QLatin1String("go-next" ))); |
251 | shiftRight->setText(i18n("Shift right" )); |
252 | connect(shiftRight, SIGNAL(triggered(bool)), SLOT(slotShiftRight())); |
253 | topToolbar->addAction(shiftRight); |
254 | |
255 | topToolbar->addSeparator(); |
256 | QAction *quit = actionCollection->addAction(KStandardAction::Quit, QLatin1String("quit" ), this, |
257 | SLOT(close())); |
258 | topToolbar->addAction(quit); |
259 | |
260 | // status in the toolbar for now (ick) |
261 | |
262 | QWidget *hbox = new QWidget(topToolbar); |
263 | QHBoxLayout *layout = new QHBoxLayout(hbox); |
264 | layout->setMargin(0); |
265 | layout->setSpacing(0); |
266 | layout->addStretch(); |
267 | |
268 | theLabel = new QLabel(statusText(), hbox); |
269 | layout->addWidget(theLabel); |
270 | topToolbar->addWidget(hbox); |
271 | |
272 | topToolbar->adjustSize(); |
273 | setMinimumWidth(topToolbar->width()); |
274 | } |
275 | |
276 | void Editor::statusChanged() |
277 | { |
278 | bool canSave = ((numTiles != 0) && ((numTiles & 1) == 0)); |
279 | theLabel->setText(statusText()); |
280 | actionCollection->action("save_board" )->setEnabled(canSave); |
281 | } |
282 | |
283 | void Editor::slotShiftLeft() |
284 | { |
285 | theBoard.shiftLeft(); |
286 | update(); |
287 | } |
288 | |
289 | void Editor::slotShiftRight() |
290 | { |
291 | theBoard.shiftRight(); |
292 | update(); |
293 | } |
294 | |
295 | void Editor::slotShiftUp() |
296 | { |
297 | theBoard.shiftUp(); |
298 | update(); |
299 | } |
300 | |
301 | void Editor::slotShiftDown() |
302 | { |
303 | theBoard.shiftDown(); |
304 | update(); |
305 | } |
306 | |
307 | void Editor::slotModeChanged(QAction *act) |
308 | { |
309 | if (act == actionCollection->action("move_tiles" )) { |
310 | mode = move; |
311 | } else if (act == actionCollection->action("del_tiles" )) { |
312 | mode = remove; |
313 | } else if (act == actionCollection->action("add_tiles" )) { |
314 | mode = insert; |
315 | } |
316 | } |
317 | |
318 | QString Editor::statusText() |
319 | { |
320 | QString buf; |
321 | |
322 | int x = currPos.x; |
323 | int y = currPos.y; |
324 | int z = currPos.e; |
325 | |
326 | if (z == 100) { |
327 | z = 0; |
328 | } else { |
329 | z = z + 1; |
330 | } |
331 | |
332 | if (x >= theBoard.m_width || x < 0 || y >= theBoard.m_height || y < 0) { |
333 | x = y = z = 0; |
334 | } |
335 | |
336 | buf = i18n("Tiles: %1 Pos: %2,%3,%4" , numTiles, x, y, z); |
337 | |
338 | return buf; |
339 | } |
340 | |
341 | |
342 | void Editor::loadBoard() |
343 | { |
344 | if (!testSave()) { |
345 | return; |
346 | } |
347 | |
348 | KUrl url = KFileDialog::getOpenUrl(KUrl(), i18n("*.layout|Board Layout (*.layout)\n*|All File" |
349 | "s" ), this, i18n("Open Board Layout" )); |
350 | |
351 | if (url.isEmpty()) { |
352 | return; |
353 | } |
354 | |
355 | theBoard.loadBoardLayout(url.path()); |
356 | update(); |
357 | } |
358 | |
359 | void Editor::newBoard() |
360 | { |
361 | // Clear out the contents of the board. Repaint the screen |
362 | // set values to their defaults. |
363 | |
364 | if (!testSave()) { |
365 | return; |
366 | } |
367 | |
368 | theBoard.clearBoardLayout(); |
369 | |
370 | clean = true; |
371 | numTiles = 0; |
372 | |
373 | statusChanged(); |
374 | update(); |
375 | } |
376 | |
377 | bool Editor::saveBoard() |
378 | { |
379 | if (!((numTiles != 0) && ((numTiles & 1) == 0))) { |
380 | KMessageBox::sorry(this, i18n( "You can only save with a even number of tiles." )); |
381 | |
382 | return false; |
383 | } |
384 | |
385 | // get a save file name |
386 | KUrl url = KFileDialog::getSaveUrl(KUrl(), i18n("*.layout|Board Layout (*.layout)\n*|All File" |
387 | "s" ), this, i18n("Save Board Layout" )); |
388 | |
389 | if (url.isEmpty()) { |
390 | return false; |
391 | } |
392 | |
393 | if (!url.isLocalFile()) { |
394 | KMessageBox::sorry(this, i18n("Only saving to local files currently supported." )); |
395 | |
396 | return false; |
397 | } |
398 | |
399 | QFileInfo f(url.path()); |
400 | if (f.exists()) { |
401 | // if it already exists, querie the user for replacement |
402 | int res = KMessageBox::warningContinueCancel(this, i18n("A file with that name already exis" |
403 | "ts. Do you wish to overwrite it?" ), i18n("Save Board Layout" ), |
404 | KStandardGuiItem::save()); |
405 | |
406 | if (res != KMessageBox::Continue) { |
407 | return false; |
408 | } |
409 | } |
410 | |
411 | bool result = theBoard.saveBoardLayout(url.path()); |
412 | |
413 | if (result == true) { |
414 | clean = true; |
415 | |
416 | return true; |
417 | } else { |
418 | return false; |
419 | } |
420 | } |
421 | |
422 | bool Editor::testSave() |
423 | { |
424 | // test if a save is required and return true if the app is to continue |
425 | // false if cancel is selected. (if ok then call out to save the board |
426 | |
427 | if (clean) { |
428 | return true; |
429 | } |
430 | |
431 | int res; |
432 | res = KMessageBox::warningYesNoCancel(this, i18n("The board has been modified. Would you like t" |
433 | "o save the changes?" ), QString(), KStandardGuiItem::save(),KStandardGuiItem::dontSave()); |
434 | |
435 | if (res == KMessageBox::Yes) { |
436 | // yes to save |
437 | if (saveBoard()) { |
438 | return true; |
439 | } else { |
440 | KMessageBox::sorry(this, i18n("Save failed. Aborting operation." )); |
441 | |
442 | return false; |
443 | } |
444 | } else { |
445 | return (res != KMessageBox::Cancel); |
446 | } |
447 | |
448 | return true; |
449 | } |
450 | |
451 | void Editor::paintEvent(QPaintEvent*) |
452 | { |
453 | // The main paint event, draw in the grid and blit in |
454 | // the tiles as specified by the layout. |
455 | |
456 | // first we layer on a background grid |
457 | QPixmap buff; |
458 | QPixmap *dest=drawFrame->getPreviewPixmap(); |
459 | buff = QPixmap(dest->width(), dest->height()); |
460 | drawBackground(&buff); |
461 | drawTiles(&buff); |
462 | QPainter p(dest); |
463 | p.drawPixmap(0, 0, buff); |
464 | p.end(); |
465 | |
466 | drawFrame->update(); |
467 | } |
468 | |
469 | void Editor::drawBackground(QPixmap *pixmap) |
470 | { |
471 | QPainter p(pixmap); |
472 | |
473 | // blast in a white background |
474 | p.fillRect(0, 0, pixmap->width(), pixmap->height(), Qt::white); |
475 | |
476 | // now put in a grid of tile quater width squares |
477 | int sy = tiles.qHeight(); |
478 | int sx = tiles.qWidth(); |
479 | |
480 | for (int y = 0; y <= theBoard.m_height; y++) { |
481 | int nextY = borderTop + (y * tiles.qHeight()); |
482 | p.drawLine(borderLeft, nextY, borderLeft + (theBoard.m_width * tiles.qWidth()), nextY); |
483 | } |
484 | |
485 | for (int x = 0; x <= theBoard.m_width; x++) { |
486 | int nextX = borderLeft + (x * tiles.qWidth()); |
487 | p.drawLine(nextX, borderTop, nextX, borderTop + (theBoard.m_height * tiles.qHeight())); |
488 | } |
489 | } |
490 | |
491 | void Editor::drawTiles(QPixmap *dest) |
492 | { |
493 | QPainter p(dest); |
494 | |
495 | int shadowX = tiles.width() - tiles.qWidth() * 2 - tiles.levelOffsetX(); |
496 | int shadowY = tiles.height() - tiles.qHeight() * 2 - tiles.levelOffsetY(); |
497 | short tile = 0; |
498 | |
499 | int xOffset = -shadowX; |
500 | int yOffset = -tiles.levelOffsetY(); |
501 | |
502 | // we iterate over the depth stacking order. Each successive level is |
503 | // drawn one indent up and to the right. The indent is the width |
504 | // of the 3d relief on the tile left (tile shadow width) |
505 | for (int z = 0; z < theBoard.m_depth; z++) { |
506 | // we draw down the board so the tile below over rights our border |
507 | for (int y = 0; y < theBoard.m_height; y++) { |
508 | // drawing right to left to prevent border overwrite |
509 | for (int x = theBoard.m_width - 1; x >= 0; x--) { |
510 | int sx = x * tiles.qWidth() + xOffset + borderLeft; |
511 | int sy = y * tiles.qHeight() + yOffset + borderTop; |
512 | |
513 | if (theBoard.getBoardData(z, y, x) != '1') { |
514 | continue; |
515 | } |
516 | |
517 | QPixmap t; |
518 | tile = (z * theBoard.m_depth) + (y * theBoard.m_height) + (x * theBoard.m_width); |
519 | // if (mode==remove && currPos.x==x && currPos.y==y && currPos.e==z) { |
520 | // t = tiles.selectedPixmaps(44)); |
521 | // } else { |
522 | t = tiles.unselectedTile(0); |
523 | // } |
524 | |
525 | // Only one compilcation. Since we render top to bottom , left |
526 | // to right situations arise where...: |
527 | // there exists a tile one q height above and to the left |
528 | // in this situation we would draw our top left border over it |
529 | // we simply split the tile draw so the top half is drawn |
530 | // minus border |
531 | if ((x > 1) && (y > 0) && theBoard.getBoardData(z, y - 1, x - 2) == '1') { |
532 | // p.drawPixmap( sx+tiles.levelOffsetX(), sy, t, tiles.levelOffsetX() , 0, |
533 | // t.width() - tiles.levelOffsetX(), t.height() / 2); |
534 | // |
535 | // p.drawPixmap(sx, sy + t.height() / 2, t, 0, t.height() / 2, t.width(), |
536 | // t.height() / 2); |
537 | |
538 | p.drawPixmap(sx, sy, t, 0, 0, t.width(), t.height()); |
539 | |
540 | p.drawPixmap(sx - tiles.qWidth() + shadowX + tiles.levelOffsetX(), sy, t, t.width() - tiles.qWidth(), t.height() - tiles.qHeight() - tiles.levelOffsetX() - shadowY, |
541 | tiles.qWidth(), tiles.qHeight() + tiles.levelOffsetX()); |
542 | } else { |
543 | |
544 | p.drawPixmap(sx, sy, t, 0, 0, t.width(), t.height()); |
545 | } |
546 | |
547 | tile++; |
548 | tile = tile % 143; |
549 | } |
550 | } |
551 | |
552 | xOffset += tiles.levelOffsetX(); |
553 | yOffset -= tiles.levelOffsetY(); |
554 | } |
555 | } |
556 | |
557 | void Editor::transformPointToPosition(const QPoint &point, POSITION &MouseClickPos, bool align) |
558 | { |
559 | // convert mouse position on screen to a tile z y x coord |
560 | // different to the one in kmahjongg.cpp since if we hit ground |
561 | // we return a result too. |
562 | |
563 | short z = 0; // shut the compiler up about maybe uninitialised errors |
564 | short y = 0; |
565 | short x = 0; |
566 | MouseClickPos.e = 100; |
567 | |
568 | // iterate over z coordinate from top to bottom |
569 | for (z = theBoard.m_depth - 1; z >= 0; --z) { |
570 | // calculate mouse coordiantes --> position in game board |
571 | // the factor -theTiles.width()/2 must keep track with the |
572 | // offset for blitting in the print zvent (FIX ME) |
573 | x = ((point.x() - borderLeft) - (z + 1) * tiles.levelOffsetX()) / tiles.qWidth(); |
574 | y = ((point.y() - borderTop) + z * tiles.levelOffsetX()) / tiles.qHeight(); |
575 | |
576 | // skip when position is illegal |
577 | if (x < 0 || x >= theBoard.m_width || y < 0 || y >= theBoard.m_height) { |
578 | continue; |
579 | } |
580 | |
581 | switch (theBoard.getBoardData(z, y, x)) { |
582 | case (UCHAR) '3': |
583 | if (align) { |
584 | x--; |
585 | y--; |
586 | } |
587 | |
588 | break; |
589 | |
590 | case (UCHAR) '2': |
591 | if (align) { |
592 | x--; |
593 | } |
594 | |
595 | break; |
596 | |
597 | case (UCHAR) '4': |
598 | if (align) { |
599 | y--; |
600 | } |
601 | |
602 | break; |
603 | |
604 | case (UCHAR) '1': |
605 | break; |
606 | |
607 | default: |
608 | continue; |
609 | } |
610 | |
611 | // if gameboard is empty, skip |
612 | if (!theBoard.getBoardData(z, y, x)) { |
613 | continue; |
614 | } |
615 | |
616 | // here, position is legal |
617 | MouseClickPos.e = z; |
618 | MouseClickPos.y = y; |
619 | MouseClickPos.x = x; |
620 | MouseClickPos.f = theBoard.getBoardData(z, y, x); |
621 | |
622 | break; |
623 | } |
624 | |
625 | if (MouseClickPos.e == 100) { |
626 | MouseClickPos.x = x; |
627 | MouseClickPos.y = y; |
628 | MouseClickPos.f=0; |
629 | } |
630 | } |
631 | |
632 | void Editor::drawFrameMousePressEvent( QMouseEvent* e ) |
633 | { |
634 | // we swallow the draw frames mouse clicks and process here |
635 | |
636 | POSITION mPos; |
637 | transformPointToPosition(e->pos(), mPos, (mode == remove)); |
638 | |
639 | switch (mode) { |
640 | case remove: |
641 | if (!theBoard.tileAbove(mPos) && mPos.e < theBoard.m_depth && theBoard.isTileAt(mPos)) { |
642 | theBoard.deleteTile(mPos); |
643 | numTiles--; |
644 | statusChanged(); |
645 | drawFrameMouseMovedEvent(e); |
646 | update(); |
647 | } |
648 | |
649 | break; |
650 | case insert: { |
651 | POSITION n = mPos; |
652 | |
653 | if (n.e == 100) { |
654 | n.e = 0; |
655 | } else { |
656 | n.e += 1; |
657 | } |
658 | |
659 | if (canInsert(n)) { |
660 | theBoard.insertTile(n); |
661 | clean = false; |
662 | numTiles++; |
663 | statusChanged(); |
664 | update(); |
665 | } |
666 | |
667 | break; |
668 | } |
669 | default: |
670 | break; |
671 | } |
672 | } |
673 | |
674 | void Editor::drawCursor(POSITION &p, bool visible) |
675 | { |
676 | int x = borderLeft + (p.e * tiles.levelOffsetX()) + (p.x * tiles.qWidth()); |
677 | int y = borderTop - ((p.e + 1) * tiles.levelOffsetY()) + (p.y * tiles.qHeight()); |
678 | int w = (tiles.qWidth() * 2) + tiles.levelOffsetX(); |
679 | int h = (tiles.qHeight() * 2) + tiles.levelOffsetY(); |
680 | |
681 | if (p.e == 100 || !visible) { |
682 | x = -1; |
683 | } |
684 | |
685 | drawFrame->setRect(x, y, w, h, tiles.levelOffsetX(), mode-remove); |
686 | drawFrame->update(); |
687 | } |
688 | |
689 | void Editor::drawFrameMouseMovedEvent(QMouseEvent *e) |
690 | { |
691 | // we swallow the draw frames mouse moves and process here |
692 | |
693 | POSITION mPos; |
694 | transformPointToPosition(e->pos(), mPos, (mode == remove)); |
695 | |
696 | if ((mPos.x==currPos.x) && (mPos.y==currPos.y) && (mPos.e==currPos.e)) { |
697 | return; |
698 | } |
699 | |
700 | currPos = mPos; |
701 | |
702 | statusChanged(); |
703 | |
704 | switch(mode) { |
705 | case insert: { |
706 | POSITION next; |
707 | next = currPos; |
708 | |
709 | if (next.e == 100) { |
710 | next.e = 0; |
711 | } else { |
712 | next.e += 1; |
713 | } |
714 | |
715 | drawCursor(next, canInsert(next)); |
716 | |
717 | break; |
718 | } |
719 | case remove: |
720 | drawCursor(currPos, 1); |
721 | |
722 | break; |
723 | case move: |
724 | break; |
725 | } |
726 | } |
727 | |
728 | bool Editor::canInsert(POSITION &p) |
729 | { |
730 | // can we inser a tile here. We can iff |
731 | // there are tiles in all positions below us (or we are a ground level) |
732 | // there are no tiles intersecting with us on this level |
733 | |
734 | if (p.e >= theBoard.m_depth) { |
735 | return false; |
736 | } |
737 | |
738 | if (p.y > theBoard.m_height - 2) { |
739 | return false; |
740 | } |
741 | |
742 | if (p.x > theBoard.m_width - 2) { |
743 | return false; |
744 | } |
745 | |
746 | POSITION n = p; |
747 | |
748 | if (p.e != 0) { |
749 | n.e -= 1; |
750 | if (!theBoard.allFilled(n)) { |
751 | return false; |
752 | } |
753 | } |
754 | |
755 | int any = theBoard.anyFilled(p); |
756 | |
757 | return (!any); |
758 | } |
759 | |
760 | void Editor::closeEvent(QCloseEvent *e) |
761 | { |
762 | if (testSave()) { |
763 | theBoard.clearBoardLayout(); |
764 | clean = true; |
765 | numTiles = 0; |
766 | statusChanged(); |
767 | update(); |
768 | |
769 | // Save the window geometry. |
770 | Prefs::setEditorGeometry(geometry()); |
771 | Prefs::self()->writeConfig(); |
772 | |
773 | e->accept(); |
774 | } else { |
775 | e->ignore(); |
776 | } |
777 | } |
778 | |
779 | void Editor::setTilesetFromSettings() |
780 | { |
781 | setTileset(Prefs::tileSet()); |
782 | } |
783 | |
784 | |
785 | #include "Editor.moc" |
786 | |