/**
* Copyright (C) 2010, LGPL
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* @author Matfyz, fyzmat@gmail.com
*/
package mines;
import java.util.List;
import mines.MinefieldContainer.Coord;
import mines.MinesUtils.MineSweeperData;
import mines.gui.generated.Ui_MinesEditor;
import com.trolltech.qt.gui.*;
/**
* Class for controlling the mines editor window.
*/
public class MinesEditor extends QDialog {
/** Suffix of the filenames, which contains the minesweeper data */
public static final String MINE_SWEEPER_DATA_SUFFIX = ".msd";
/** GUI for this window */
Ui_MinesEditor ui = new Ui_MinesEditor();
/** Real and viewed contents of the edited minefield */
MineSweeperData mEditorData = new MineSweeperData();
/** Signals, that the edited minefield was accepted */
public Signal1<MineSweeperData> mAcceptedSignal = new Signal1<MineSweeperData>();
/**
* Initializes the GUI and connects it with the logic.
* @param parent Parent window.
*/
public MinesEditor(QWidget parent) {
super(parent);
ui.setupUi(this);
ui.mCloseButton.clicked.connect(this, "accept()");
ui.mLoadButton.clicked.connect(this, "loadButtonClicked()");
ui.mSaveButton.clicked.connect(this, "saveButtonClicked()");
this.accepted.connect(this, "onAccepted()");
}
/**
* Signal handler, when this dialog is closed to perform the edited changes.
*/
void onAccepted() {
mAcceptedSignal.emit(mEditorData);
}
/**
* Sets the dialog data and shows the dialog.
* @param data Real and viewed contents of the minefield to be shown.
*/
void runDialog(MineSweeperData data) {
setContent(data.mRealContent, data.mViewedContent);
exec();
}
/**
* Signal handler, when the load minefield from file button is clicked.
*/
void loadButtonClicked() {
// open the choose file dialog
String caption = "Open minesweeper data";
String directory = ".";
String filterString = "Minesweeper data (*" + MINE_SWEEPER_DATA_SUFFIX + ")";
QFileDialog.Filter filter = new QFileDialog.Filter(filterString);
String filename = QFileDialog.getOpenFileName(this, caption, directory, filter);
if (filename.equals("")) {
return;
}
// load the new minefield
MineSweeperData data = MinesUtils.loadObjectFromFileSafely(filename);
if ((data.mRealContent != null) && (data.mViewedContent != null)) {
setContent(data.mRealContent, data.mViewedContent);
}
}
/**
* Signal handler, when the save minefield to file button is clicked.
*/
void saveButtonClicked() {
// open the choose file dialog
String caption = "Save minesweeper data";
String directory = ".";
String filterString = "Minesweeper data (*" + MINE_SWEEPER_DATA_SUFFIX + ")";
QFileDialog.Filter filter = new QFileDialog.Filter(filterString);
String filename = QFileDialog.getSaveFileName(this, caption, directory, filter);
if (filename.equals("")) {
return;
}
// save the edited minefield
MinesUtils.saveMinefieldToFileSafely(mEditorData, filename);
}
/**
* Sets a new minefield to be edited.
* @param realContent The real content of the minefield.
* @param viewedContent The viewed content of the minefield.
*/
public void setContent(MinefieldContainer<GUI_FIELD> realContent,
MinefieldContainer<GUI_FIELD> viewedContent) {
mEditorData.mRealContent = new MinefieldContainer<GUI_FIELD>(realContent);
mEditorData.mViewedContent = new MinefieldContainer<GUI_FIELD>(viewedContent);
ui.minefieldView_real.connectToButtonsLeftClick(this, "realMinefieldClicked(MinefieldContainer$Coord)");
ui.minefieldView_view.connectToButtonsLeftClick(this, "viewedMinefieldClicked(MinefieldContainer$Coord)");
ui.minefieldView_real.createMinefield(mEditorData.mRealContent);
ui.minefieldView_view.createMinefield(mEditorData.mViewedContent);
}
/**
* Signal handler, when the real view of minefield was clicked. It puts or picks up
* a mine on the clicked field.
* @param clickedCoord Coordinates of the clicked field.
*/
public void realMinefieldClicked(Coord clickedCoord) {
GUI_FIELD real_type = mEditorData.mRealContent.get(clickedCoord);
// put or pick up the mine depending on the current real value
if(real_type.equals(GUI_FIELD.MINE)) {
mEditorData.mRealContent.set(clickedCoord, GUI_FIELD.ZERO);
} else {
mEditorData.mRealContent.set(clickedCoord, GUI_FIELD.MINE);
}
// update the real values according to the last change
MinesUtils.updateFieldsNumbers(mEditorData.mRealContent);
// draw the changed real minefield
ui.minefieldView_real.createMinefield(mEditorData.mRealContent);
// we also have to update the neighbourhood of the clicked field in
// the viewed content
List<Coord> aroundCoords = mEditorData.mRealContent.getAroundFields(clickedCoord);
for (Coord aroundCoord : aroundCoords) {
GUI_FIELD updated_real_type = mEditorData.mRealContent.get(aroundCoord);
GUI_FIELD view_type = mEditorData.mViewedContent.get(aroundCoord);
// we need to update only uncovered fields
if (!view_type.equals(GUI_FIELD.COVERED)) {
// we will make a flag on the uncovered minefield, otherwise
// we will show the real number
updated_real_type = (updated_real_type.equals(GUI_FIELD.MINE))
? GUI_FIELD.FLAG : updated_real_type;
mEditorData.mViewedContent.set(aroundCoord, updated_real_type);
}
}
ui.minefieldView_view.createMinefield(mEditorData.mViewedContent);
}
/**
* Signal handler, when the viewed view of the minefield (content of minefield
* seen by the player) is clicked. It covers/uncovers the clicked field.
* @param clickedCoord Coordinates of the clicked field.
*/
public void viewedMinefieldClicked(Coord clickedCoord) {
GUI_FIELD type = mEditorData.mViewedContent.get(clickedCoord);
if(type.equals(GUI_FIELD.COVERED)) {
// we have to uncover the button with proper value
GUI_FIELD real_type = mEditorData.mRealContent.get(clickedCoord);
GUI_FIELD view_type = real_type.equals(GUI_FIELD.MINE) ? GUI_FIELD.FLAG : real_type;
mEditorData.mViewedContent.set(clickedCoord, view_type);
} else {
mEditorData.mViewedContent.set(clickedCoord, GUI_FIELD.COVERED);
}
ui.minefieldView_view.createMinefield(mEditorData.mViewedContent);
}
}