* Renamed "Store Current" to "Snapshot Current", and "Restore Saved" to

"Restore Snapshot".
* Implemented a simple undo/redo.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22987 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-11-24 14:36:13 +00:00
parent 91b75ef2fd
commit 3b54b5c49e
5 changed files with 112 additions and 4 deletions
+2
View File
@@ -2,6 +2,8 @@ SubDir HAIKU_TOP src apps sudoku ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders shared ;
Application Sudoku :
CenteredViewContainer.cpp
ProgressWindow.cpp
+69
View File
@@ -144,6 +144,7 @@ SudokuView::SetTo(entry_ref& ref)
}
}
_PushUndo();
status = fField->SetTo(_BaseCharacter(), buffer);
Invalidate();
return status;
@@ -164,6 +165,7 @@ SudokuView::SetTo(const char* data)
if (status < B_OK)
return B_BAD_VALUE;
_PushUndo();
status = fField->SetTo(_BaseCharacter(), buffer);
Invalidate();
return status;
@@ -176,6 +178,7 @@ SudokuView::SetTo(SudokuField* field)
if (field == NULL || field == fField)
return B_BAD_VALUE;
_PushUndo();
delete fField;
fField = field;
@@ -222,6 +225,8 @@ SudokuView::SaveTo(entry_ref& ref, bool asText)
void
SudokuView::ClearChanged()
{
_PushUndo();
for (uint32 y = 0; y < fField->Size(); y++) {
for (uint32 x = 0; x < fField->Size(); x++) {
if ((fField->FlagsAt(x, y) & kInitialValue) == 0)
@@ -236,6 +241,7 @@ SudokuView::ClearChanged()
void
SudokuView::ClearAll()
{
_PushUndo();
fField->Reset();
Invalidate();
}
@@ -413,6 +419,55 @@ SudokuView::_RemoveHint()
}
void
SudokuView::_UndoRedo(BObjectList<BMessage>& undos,
BObjectList<BMessage>& redos)
{
if (undos.IsEmpty())
return;
BMessage* undo = undos.RemoveItemAt(undos.CountItems() - 1);
BMessage* redo = new BMessage;
if (fField->Archive(redo, true) == B_OK)
redos.AddItem(redo);
SudokuField field(undo);
delete undo;
fField->SetTo(&field);
SendNotices(kUndoRedoChanged);
Invalidate();
}
void
SudokuView::Undo()
{
_UndoRedo(fUndos, fRedos);
}
void
SudokuView::Redo()
{
_UndoRedo(fRedos, fUndos);
}
void
SudokuView::_PushUndo()
{
fRedos.MakeEmpty();
BMessage* undo = new BMessage;
if (fField->Archive(undo, true) == B_OK
&& fUndos.AddItem(undo))
SendNotices(kUndoRedoChanged);
}
void
SudokuView::MouseDown(BPoint where)
{
@@ -433,6 +488,7 @@ SudokuView::MouseDown(BPoint where)
uint32 value = hintX + hintY * fBlockSize;
uint32 field = x + y * fField->Size();
_PushUndo();
if (clicks == 2 && fLastHintValue == value && fLastField == field
|| (buttons & (B_SECONDARY_MOUSE_BUTTON
@@ -540,6 +596,7 @@ SudokuView::_InsertKey(char rawKey, int32 modifiers)
if (value == 0)
return;
_PushUndo();
uint32 hintMask = fField->HintMaskAt(fKeyboardX, fKeyboardY);
uint32 valueMask = 1UL << (value - 1);
if (modifiers & B_OPTION_KEY)
@@ -550,6 +607,7 @@ SudokuView::_InsertKey(char rawKey, int32 modifiers)
fField->SetValueAt(fKeyboardX, fKeyboardY, 0);
fField->SetHintMaskAt(fKeyboardX, fKeyboardY, hintMask);
} else {
_PushUndo();
fField->SetValueAt(fKeyboardX, fKeyboardY, value);
if (value)
BMessenger(this).SendMessage(kMsgCheckSolved);
@@ -638,6 +696,14 @@ SudokuView::MessageReceived(BMessage* message)
}
break;
case B_UNDO:
Undo();
break;
case B_REDO:
Redo();
break;
case kMsgSolveSudoku:
{
SudokuSolver solver;
@@ -647,6 +713,7 @@ SudokuView::MessageReceived(BMessage* message)
printf("found %ld solutions in %g msecs\n",
solver.CountSolutions(), (system_time() - start) / 1000.0);
if (solver.CountSolutions() > 0) {
_PushUndo();
fField->SetTo(solver.SolutionAt(0));
Invalidate();
} else
@@ -668,6 +735,8 @@ SudokuView::MessageReceived(BMessage* message)
printf("found %ld solutions in %g msecs\n",
solver.CountSolutions(), (system_time() - start) / 1000.0);
if (solver.CountSolutions() > 0) {
_PushUndo();
// find free spot
uint32 x, y;
do {
+13
View File
@@ -7,6 +7,7 @@
#include <View.h>
#include <ObjectList.h>
class SudokuField;
struct entry_ref;
@@ -43,6 +44,11 @@ public:
void SetEditable(bool editable);
bool Editable() const { return fEditable; }
bool CanUndo() { return !fUndos.IsEmpty(); }
bool CanRedo() { return !fRedos.IsEmpty(); }
void Undo();
void Redo();
protected:
virtual void AttachedToWindow();
@@ -75,9 +81,13 @@ private:
void _FitFont(BFont& font, float width, float height);
void _DrawKeyboardFocus();
void _DrawHints(uint32 x, uint32 y);
void _UndoRedo(BObjectList<BMessage>& undos, BObjectList<BMessage>& redos);
void _PushUndo();
rgb_color fBackgroundColor;
SudokuField* fField;
BObjectList<BMessage> fUndos;
BObjectList<BMessage> fRedos;
uint32 fBlockSize;
float fWidth, fHeight, fBaseline;
BFont fFieldFont;
@@ -98,4 +108,7 @@ static const uint32 kMsgSudokuSolved = 'susl';
static const uint32 kMsgSolveSudoku = 'slvs';
static const uint32 kMsgSolveSingle = 'slsg';
// you can observe these:
static const int32 kUndoRedoChanged = 'unre';
#endif // SUDOKU_VIEW_H
+26 -4
View File
@@ -210,8 +210,7 @@ SudokuWindow::SudokuWindow()
new BMessage(B_ABOUT_REQUESTED)));
menu->AddSeparatorItem();
menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED),
'Q', B_COMMAND_KEY));
menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
menu->SetTargetForItems(this);
item->SetTarget(be_app);
menuBar->AddItem(menu);
@@ -231,8 +230,15 @@ SudokuWindow::SudokuWindow()
// "Help" menu
menu = new BMenu("Help");
menu->AddItem(new BMenuItem("Store Current", new BMessage(kMsgStoreState)));
menu->AddItem(fRestoreStateItem = new BMenuItem("Restore Saved",
menu->AddItem(fUndoItem = new BMenuItem("Undo", new BMessage(B_UNDO), 'Z'));
fUndoItem->SetEnabled(false);
menu->AddItem(fRedoItem = new BMenuItem("Redo", new BMessage(B_REDO), 'Z',
B_SHIFT_KEY));
fRedoItem->SetEnabled(false);
menu->AddSeparatorItem();
menu->AddItem(new BMenuItem("Snapshot Current", new BMessage(kMsgStoreState)));
menu->AddItem(fRestoreStateItem = new BMenuItem("Restore Snapshot",
new BMessage(kMsgRestoreState)));
fRestoreStateItem->SetEnabled(fStoredState != NULL);
menu->AddSeparatorItem();
@@ -248,6 +254,9 @@ SudokuWindow::SudokuWindow()
fSavePanel = new BFilePanel(B_SAVE_PANEL);
fSavePanel->SetTarget(this);
fSudokuView->StartWatching(this, kUndoRedoChanged);
// we like to know whenever the undo/redo state changes
fProgressWindow = new ProgressWindow(this,
new BMessage(kMsgAbortSudokuGenerator));
}
@@ -499,6 +508,19 @@ SudokuWindow::MessageReceived(BMessage* message)
B_WIDTH_AS_USUAL, B_IDEA_ALERT))->Go();
break;
case B_OBSERVER_NOTICE_CHANGE:
{
int32 what;
if (message->FindInt32(B_OBSERVE_WHAT_CHANGE, &what) != B_OK)
break;
if (what == kUndoRedoChanged) {
fUndoItem->SetEnabled(fSudokuView->CanUndo());
fRedoItem->SetEnabled(fSudokuView->CanRedo());
}
break;
}
default:
BWindow::MessageReceived(message);
break;
+2
View File
@@ -39,6 +39,8 @@ private:
SudokuView* fSudokuView;
GenerateSudoku* fGenerator;
BMenuItem* fRestoreStateItem;
BMenuItem* fUndoItem;
BMenuItem* fRedoItem;
BMessage* fStoredState;
};