From fc64ef86ff1b21aa6ddd5542796c96a22d0a2410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 8 Jan 2015 17:17:39 +0100 Subject: [PATCH] Sudoku: reordered SudokuView's methods. * Their declaration order now matches their implementation order. --- src/apps/sudoku/SudokuView.cpp | 878 +++++++++++++++++---------------- src/apps/sudoku/SudokuView.h | 29 +- 2 files changed, 458 insertions(+), 449 deletions(-) diff --git a/src/apps/sudoku/SudokuView.cpp b/src/apps/sudoku/SudokuView.cpp index 34a0f3cf1f..c26e2f9b22 100644 --- a/src/apps/sudoku/SudokuView.cpp +++ b/src/apps/sudoku/SudokuView.cpp @@ -45,10 +45,11 @@ extern const char* kSignature; SudokuView::SudokuView(BRect frame, const char* name, const BMessage& settings, uint32 resizingMode) - : BView(frame, name, resizingMode, + : + BView(frame, name, resizingMode, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS) { - InitObject(&settings); + _InitObject(&settings); #if 0 BRect rect(Bounds()); @@ -61,9 +62,10 @@ SudokuView::SudokuView(BRect frame, const char* name, SudokuView::SudokuView(BMessage* archive) - : BView(archive) + : + BView(archive) { - InitObject(archive); + _InitObject(archive); } @@ -106,46 +108,6 @@ SudokuView::Instantiate(BMessage* archive) } -void -SudokuView::InitObject(const BMessage* archive) -{ - fField = NULL; - fShowHintX = UINT32_MAX; - fValueHintValue = UINT32_MAX; - fLastHintValue = UINT32_MAX; - fLastField = UINT32_MAX; - fKeyboardX = 0; - fKeyboardY = 0; - fShowKeyboardFocus = false; - fEditable = true; - - BMessage field; - if (archive->FindMessage("field", &field) == B_OK) { - fField = new SudokuField(&field); - if (fField->InitCheck() != B_OK) { - delete fField; - fField = NULL; - } else if (fField->IsSolved()) - ClearAll(); - } - if (fField == NULL) - fField = new SudokuField(3); - - fBlockSize = fField->BlockSize(); - - if (archive->FindInt32("hint flags", (int32*)&fHintFlags) != B_OK) - fHintFlags = kMarkInvalid; - if (archive->FindBool("show cursor", &fShowCursor) != B_OK) - fShowCursor = false; - - SetViewColor(B_TRANSPARENT_COLOR); - // to avoid flickering - fBackgroundColor = kBackgroundColor; - SetLowColor(fBackgroundColor); - FrameResized(0, 0); -} - - status_t SudokuView::SaveState(BMessage& state) const { @@ -162,35 +124,6 @@ SudokuView::SaveState(BMessage& state) const } -status_t -SudokuView::_FilterString(const char* data, size_t dataLength, char* buffer, - uint32& out, bool& ignore) -{ - uint32 maxOut = fField->Size() * fField->Size(); - - for (uint32 i = 0; i < dataLength && data[i]; i++) { - if (data[i] == '#') - ignore = true; - else if (data[i] == '\n') - ignore = false; - - if (ignore || isspace(data[i])) - continue; - - if (!_ValidCharacter(data[i])) { - return B_BAD_VALUE; - } - - buffer[out++] = data[i]; - if (out == maxOut) - break; - } - - buffer[out] = '\0'; - return B_OK; -} - - status_t SudokuView::SetTo(entry_ref& ref) { @@ -593,27 +526,26 @@ SudokuView::SetEditable(bool editable) void -SudokuView::AttachedToWindow() +SudokuView::Undo() { - MakeFocus(true); + _UndoRedo(fUndos, fRedos); } void -SudokuView::_FitFont(BFont& font, float fieldWidth, float fieldHeight) +SudokuView::Redo() { - font.SetSize(100); + _UndoRedo(fRedos, fUndos); +} - font_height fontHeight; - font.GetHeight(&fontHeight); - float width = font.StringWidth("W"); - float height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); +// #pragma mark - BWindow methods - float factor = fieldWidth != fHintWidth ? 4.f / 5.f : 1.f; - float widthFactor = fieldWidth / (width / factor); - float heightFactor = fieldHeight / (height / factor); - font.SetSize(100 * min_c(widthFactor, heightFactor)); + +void +SudokuView::AttachedToWindow() +{ + MakeFocus(true); } @@ -650,248 +582,6 @@ SudokuView::FrameResized(float /*width*/, float /*height*/) } -BPoint -SudokuView::_LeftTop(uint32 x, uint32 y) -{ - return BPoint(x * fWidth - 1 + x / fBlockSize * kStrongLineSize + 1, - y * fHeight - 1 + y / fBlockSize * kStrongLineSize + 1); -} - - -BRect -SudokuView::_Frame(uint32 x, uint32 y) -{ - BPoint leftTop = _LeftTop(x, y); - BPoint rightBottom = leftTop + BPoint(fWidth - 2, fHeight - 2); - - return BRect(leftTop, rightBottom); -} - - -void -SudokuView::_InvalidateHintField(uint32 x, uint32 y, uint32 hintX, - uint32 hintY) -{ - BPoint leftTop = _LeftTop(x, y); - leftTop.x += hintX * fHintWidth; - leftTop.y += hintY * fHintHeight; - BPoint rightBottom = leftTop; - rightBottom.x += fHintWidth; - rightBottom.y += fHintHeight; - - Invalidate(BRect(leftTop, rightBottom)); -} - - -void -SudokuView::_InvalidateField(uint32 x, uint32 y) -{ - Invalidate(_Frame(x, y)); -} - - -void -SudokuView::_InvalidateValue(uint32 value, bool invalidateHint, - uint32 fieldX, uint32 fieldY) -{ - for (uint32 y = 0; y < fField->Size(); y++) { - for (uint32 x = 0; x < fField->Size(); x++) { - if (fField->ValueAt(x, y) == value || (x == fieldX && y == fieldY)) - Invalidate(_Frame(x, y)); - else if (invalidateHint && fField->ValueAt(x, y) == 0 - && fField->HasHint(x, y, value)) - Invalidate(_Frame(x, y)); - } - } -} - - -void -SudokuView::_InvalidateKeyboardFocus(uint32 x, uint32 y) -{ - BRect frame = _Frame(x, y); - frame.InsetBy(-1, -1); - Invalidate(frame); -} - - -bool -SudokuView::_GetHintFieldFor(BPoint where, uint32 x, uint32 y, - uint32& hintX, uint32& hintY) -{ - BPoint leftTop = _LeftTop(x, y); - hintX = (uint32)floor((where.x - leftTop.x) / fHintWidth); - hintY = (uint32)floor((where.y - leftTop.y) / fHintHeight); - - if (hintX >= fBlockSize || hintY >= fBlockSize) - return false; - - return true; -} - - -bool -SudokuView::_GetFieldFor(BPoint where, uint32& x, uint32& y) -{ - float block = fWidth * fBlockSize + kStrongLineSize; - x = (uint32)floor(where.x / block); - uint32 offsetX = (uint32)floor((where.x - x * block) / fWidth); - x = x * fBlockSize + offsetX; - - block = fHeight * fBlockSize + kStrongLineSize; - y = (uint32)floor(where.y / block); - uint32 offsetY = (uint32)floor((where.y - y * block) / fHeight); - y = y * fBlockSize + offsetY; - - if (offsetX >= fBlockSize || offsetY >= fBlockSize - || x >= fField->Size() || y >= fField->Size()) - return false; - - return true; -} - - -void -SudokuView::_SetValueHintValue(uint32 value) -{ - if (value == fValueHintValue) - return; - - if (fValueHintValue != UINT32_MAX) - _InvalidateValue(fValueHintValue, true); - - fValueHintValue = value; - - if (fValueHintValue != UINT32_MAX) - _InvalidateValue(fValueHintValue, true); -} - - -void -SudokuView::_RemoveHint() -{ - if (fShowHintX == UINT32_MAX) - return; - - uint32 x = fShowHintX; - uint32 y = fShowHintY; - fShowHintX = UINT32_MAX; - fShowHintY = UINT32_MAX; - - _InvalidateField(x, y); -} - - -void -SudokuView::_ToggleValue(uint32 x, uint32 y, uint32 value, uint32 field) -{ - bool wasCompleted; - if (fField->ValueAt(x, y) > 0) { - // Remove value - value = fField->ValueAt(x, y) - 1; - wasCompleted = fField->IsValueCompleted(value + 1); - - fField->SetValueAt(x, y, 0); - fShowHintX = x; - fShowHintY = y; - } else { - // Set value - wasCompleted = fField->IsValueCompleted(value + 1); - - fField->SetValueAt(x, y, value + 1); - BMessenger(this).SendMessage(kMsgCheckSolved); - - // allow dragging to remove the hint from other fields - fLastHintValueSet = false; - fLastHintValue = value; - fLastField = field; - } - - if (value + 1 != fValueHintValue && fValueHintValue != ~0UL) - _SetValueHintValue(value + 1); - - if (wasCompleted != fField->IsValueCompleted(value + 1)) - _InvalidateValue(value + 1, false, x, y); - else - _InvalidateField(x, y); -} - - -void -SudokuView::_ToggleHintValue(uint32 x, uint32 y, uint32 hintX, uint32 hintY, - uint32 value, uint32 field) -{ - uint32 hintMask = fField->HintMaskAt(x, y); - uint32 valueMask = 1UL << value; - fLastHintValueSet = (hintMask & valueMask) == 0; - - if (fLastHintValueSet) - hintMask |= valueMask; - else - hintMask &= ~valueMask; - - fField->SetHintMaskAt(x, y, hintMask); - - if (value + 1 != fValueHintValue) { - _SetValueHintValue(UINT32_MAX); - _InvalidateHintField(x, y, hintX, hintY); - } else - _InvalidateField(x, y); - - fLastHintValue = value; - fLastField = field; -} - - -void -SudokuView::_UndoRedo(BObjectList& undos, - BObjectList& 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) { @@ -994,39 +684,6 @@ SudokuView::MouseMoved(BPoint where, uint32 transit, } -void -SudokuView::_InsertKey(char rawKey, int32 modifiers) -{ - if (!fEditable || !_ValidCharacter(rawKey) - || fField->IsInitialValue(fKeyboardX, fKeyboardY)) - return; - - uint32 value = rawKey - _BaseCharacter(); - - if (modifiers & (B_SHIFT_KEY | B_OPTION_KEY)) { - // set or remove hint - if (value == 0) - return; - - _PushUndo(); - uint32 hintMask = fField->HintMaskAt(fKeyboardX, fKeyboardY); - uint32 valueMask = 1UL << (value - 1); - if (modifiers & B_OPTION_KEY) - hintMask &= ~valueMask; - else - hintMask |= valueMask; - - fField->SetValueAt(fKeyboardX, fKeyboardY, 0); - fField->SetHintMaskAt(fKeyboardX, fKeyboardY, hintMask); - } else { - _PushUndo(); - fField->SetValueAt(fKeyboardX, fKeyboardY, value); - if (value) - BMessenger(this).SendMessage(kMsgCheckSolved); - } -} - - void SudokuView::KeyDown(const char *bytes, int32 /*numBytes*/) { @@ -1135,81 +792,6 @@ SudokuView::MessageReceived(BMessage* message) } -char -SudokuView::_BaseCharacter() -{ - return fField->Size() > 9 ? '@' : '0'; -} - - -bool -SudokuView::_ValidCharacter(char c) -{ - char min = _BaseCharacter(); - char max = min + fField->Size(); - return c >= min && c <= max; -} - - -void -SudokuView::_SetText(char* text, uint32 value) -{ - text[0] = value + _BaseCharacter(); - text[1] = '\0'; -} - - -void -SudokuView::_DrawKeyboardFocus() -{ - BRect frame = _Frame(fKeyboardX, fKeyboardY); - SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); - StrokeRect(frame); - frame.InsetBy(-1, -1); - StrokeRect(frame); - frame.InsetBy(2, 2); - StrokeRect(frame); -} - - -void -SudokuView::_DrawHints(uint32 x, uint32 y) -{ - bool showAll = fShowHintX == x && fShowHintY == y; - uint32 hintMask = fField->HintMaskAt(x, y); - if (hintMask == 0 && !showAll) - return; - - uint32 validMask = fField->ValidMaskAt(x, y); - BPoint leftTop = _LeftTop(x, y); - SetFont(&fHintFont); - - for (uint32 j = 0; j < fBlockSize; j++) { - for (uint32 i = 0; i < fBlockSize; i++) { - uint32 value = j * fBlockSize + i; - if ((hintMask & (1UL << value)) != 0) { - SetHighColor(kHintColor); - } else { - if (!showAll) - continue; - - if ((fHintFlags & kMarkValidHints) == 0 - || (validMask & (1UL << value)) != 0) - SetHighColor(110, 110, 80); - else - SetHighColor(180, 180, 120); - } - - char text[2]; - _SetText(text, value + 1); - DrawString(text, leftTop + BPoint((i + 0.5f) * fHintWidth - - StringWidth(text) / 2, floorf(j * fHintHeight) - + fHintBaseline)); - } - } -} - - void SudokuView::Draw(BRect /*updateRect*/) { @@ -1299,6 +881,297 @@ SudokuView::Draw(BRect /*updateRect*/) } +// #pragma mark - Private methods + + +void +SudokuView::_InitObject(const BMessage* archive) +{ + fField = NULL; + fShowHintX = UINT32_MAX; + fValueHintValue = UINT32_MAX; + fLastHintValue = UINT32_MAX; + fLastField = UINT32_MAX; + fKeyboardX = 0; + fKeyboardY = 0; + fShowKeyboardFocus = false; + fEditable = true; + + BMessage field; + if (archive->FindMessage("field", &field) == B_OK) { + fField = new SudokuField(&field); + if (fField->InitCheck() != B_OK) { + delete fField; + fField = NULL; + } else if (fField->IsSolved()) + ClearAll(); + } + if (fField == NULL) + fField = new SudokuField(3); + + fBlockSize = fField->BlockSize(); + + if (archive->FindInt32("hint flags", (int32*)&fHintFlags) != B_OK) + fHintFlags = kMarkInvalid; + if (archive->FindBool("show cursor", &fShowCursor) != B_OK) + fShowCursor = false; + + SetViewColor(B_TRANSPARENT_COLOR); + // to avoid flickering + fBackgroundColor = kBackgroundColor; + SetLowColor(fBackgroundColor); + FrameResized(0, 0); +} + + +status_t +SudokuView::_FilterString(const char* data, size_t dataLength, char* buffer, + uint32& out, bool& ignore) +{ + uint32 maxOut = fField->Size() * fField->Size(); + + for (uint32 i = 0; i < dataLength && data[i]; i++) { + if (data[i] == '#') + ignore = true; + else if (data[i] == '\n') + ignore = false; + + if (ignore || isspace(data[i])) + continue; + + if (!_ValidCharacter(data[i])) { + return B_BAD_VALUE; + } + + buffer[out++] = data[i]; + if (out == maxOut) + break; + } + + buffer[out] = '\0'; + return B_OK; +} + + +void +SudokuView::_SetText(char* text, uint32 value) +{ + text[0] = value + _BaseCharacter(); + text[1] = '\0'; +} + + +char +SudokuView::_BaseCharacter() +{ + return fField->Size() > 9 ? '@' : '0'; +} + + +bool +SudokuView::_ValidCharacter(char c) +{ + char min = _BaseCharacter(); + char max = min + fField->Size(); + return c >= min && c <= max; +} + + +BPoint +SudokuView::_LeftTop(uint32 x, uint32 y) +{ + return BPoint(x * fWidth - 1 + x / fBlockSize * kStrongLineSize + 1, + y * fHeight - 1 + y / fBlockSize * kStrongLineSize + 1); +} + + +BRect +SudokuView::_Frame(uint32 x, uint32 y) +{ + BPoint leftTop = _LeftTop(x, y); + BPoint rightBottom = leftTop + BPoint(fWidth - 2, fHeight - 2); + + return BRect(leftTop, rightBottom); +} + + +void +SudokuView::_InvalidateHintField(uint32 x, uint32 y, uint32 hintX, + uint32 hintY) +{ + BPoint leftTop = _LeftTop(x, y); + leftTop.x += hintX * fHintWidth; + leftTop.y += hintY * fHintHeight; + BPoint rightBottom = leftTop; + rightBottom.x += fHintWidth; + rightBottom.y += fHintHeight; + + Invalidate(BRect(leftTop, rightBottom)); +} + + +void +SudokuView::_InvalidateField(uint32 x, uint32 y) +{ + Invalidate(_Frame(x, y)); +} + + +void +SudokuView::_InvalidateValue(uint32 value, bool invalidateHint, + uint32 fieldX, uint32 fieldY) +{ + for (uint32 y = 0; y < fField->Size(); y++) { + for (uint32 x = 0; x < fField->Size(); x++) { + if (fField->ValueAt(x, y) == value || (x == fieldX && y == fieldY)) + Invalidate(_Frame(x, y)); + else if (invalidateHint && fField->ValueAt(x, y) == 0 + && fField->HasHint(x, y, value)) + Invalidate(_Frame(x, y)); + } + } +} + + +void +SudokuView::_InvalidateKeyboardFocus(uint32 x, uint32 y) +{ + BRect frame = _Frame(x, y); + frame.InsetBy(-1, -1); + Invalidate(frame); +} + + +void +SudokuView::_InsertKey(char rawKey, int32 modifiers) +{ + if (!fEditable || !_ValidCharacter(rawKey) + || fField->IsInitialValue(fKeyboardX, fKeyboardY)) + return; + + uint32 value = rawKey - _BaseCharacter(); + + if (modifiers & (B_SHIFT_KEY | B_OPTION_KEY)) { + // set or remove hint + if (value == 0) + return; + + _PushUndo(); + uint32 hintMask = fField->HintMaskAt(fKeyboardX, fKeyboardY); + uint32 valueMask = 1UL << (value - 1); + if (modifiers & B_OPTION_KEY) + hintMask &= ~valueMask; + else + hintMask |= valueMask; + + fField->SetValueAt(fKeyboardX, fKeyboardY, 0); + fField->SetHintMaskAt(fKeyboardX, fKeyboardY, hintMask); + } else { + _PushUndo(); + fField->SetValueAt(fKeyboardX, fKeyboardY, value); + if (value) + BMessenger(this).SendMessage(kMsgCheckSolved); + } +} + + +bool +SudokuView::_GetHintFieldFor(BPoint where, uint32 x, uint32 y, + uint32& hintX, uint32& hintY) +{ + BPoint leftTop = _LeftTop(x, y); + hintX = (uint32)floor((where.x - leftTop.x) / fHintWidth); + hintY = (uint32)floor((where.y - leftTop.y) / fHintHeight); + + if (hintX >= fBlockSize || hintY >= fBlockSize) + return false; + + return true; +} + + +bool +SudokuView::_GetFieldFor(BPoint where, uint32& x, uint32& y) +{ + float block = fWidth * fBlockSize + kStrongLineSize; + x = (uint32)floor(where.x / block); + uint32 offsetX = (uint32)floor((where.x - x * block) / fWidth); + x = x * fBlockSize + offsetX; + + block = fHeight * fBlockSize + kStrongLineSize; + y = (uint32)floor(where.y / block); + uint32 offsetY = (uint32)floor((where.y - y * block) / fHeight); + y = y * fBlockSize + offsetY; + + if (offsetX >= fBlockSize || offsetY >= fBlockSize + || x >= fField->Size() || y >= fField->Size()) + return false; + + return true; +} + + +void +SudokuView::_ToggleValue(uint32 x, uint32 y, uint32 value, uint32 field) +{ + bool wasCompleted; + if (fField->ValueAt(x, y) > 0) { + // Remove value + value = fField->ValueAt(x, y) - 1; + wasCompleted = fField->IsValueCompleted(value + 1); + + fField->SetValueAt(x, y, 0); + fShowHintX = x; + fShowHintY = y; + } else { + // Set value + wasCompleted = fField->IsValueCompleted(value + 1); + + fField->SetValueAt(x, y, value + 1); + BMessenger(this).SendMessage(kMsgCheckSolved); + + // allow dragging to remove the hint from other fields + fLastHintValueSet = false; + fLastHintValue = value; + fLastField = field; + } + + if (value + 1 != fValueHintValue && fValueHintValue != ~0UL) + _SetValueHintValue(value + 1); + + if (wasCompleted != fField->IsValueCompleted(value + 1)) + _InvalidateValue(value + 1, false, x, y); + else + _InvalidateField(x, y); +} + + +void +SudokuView::_ToggleHintValue(uint32 x, uint32 y, uint32 hintX, uint32 hintY, + uint32 value, uint32 field) +{ + uint32 hintMask = fField->HintMaskAt(x, y); + uint32 valueMask = 1UL << value; + fLastHintValueSet = (hintMask & valueMask) == 0; + + if (fLastHintValueSet) + hintMask |= valueMask; + else + hintMask &= ~valueMask; + + fField->SetHintMaskAt(x, y, hintMask); + + if (value + 1 != fValueHintValue) { + _SetValueHintValue(UINT32_MAX); + _InvalidateHintField(x, y, hintX, hintY); + } else + _InvalidateField(x, y); + + fLastHintValue = value; + fLastField = field; +} + + void SudokuView::_SetAllHints() { @@ -1366,3 +1239,138 @@ SudokuView::_GetSolutions(SudokuSolver& solver) return solver.CountSolutions() > 0; } + + +void +SudokuView::_UndoRedo(BObjectList& undos, + BObjectList& 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::_PushUndo() +{ + fRedos.MakeEmpty(); + + BMessage* undo = new BMessage; + if (fField->Archive(undo, true) == B_OK + && fUndos.AddItem(undo)) + SendNotices(kUndoRedoChanged); +} + + +void +SudokuView::_SetValueHintValue(uint32 value) +{ + if (value == fValueHintValue) + return; + + if (fValueHintValue != UINT32_MAX) + _InvalidateValue(fValueHintValue, true); + + fValueHintValue = value; + + if (fValueHintValue != UINT32_MAX) + _InvalidateValue(fValueHintValue, true); +} + + +void +SudokuView::_RemoveHint() +{ + if (fShowHintX == UINT32_MAX) + return; + + uint32 x = fShowHintX; + uint32 y = fShowHintY; + fShowHintX = UINT32_MAX; + fShowHintY = UINT32_MAX; + + _InvalidateField(x, y); +} + + +void +SudokuView::_FitFont(BFont& font, float fieldWidth, float fieldHeight) +{ + font.SetSize(100); + + font_height fontHeight; + font.GetHeight(&fontHeight); + + float width = font.StringWidth("W"); + float height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); + + float factor = fieldWidth != fHintWidth ? 4.f / 5.f : 1.f; + float widthFactor = fieldWidth / (width / factor); + float heightFactor = fieldHeight / (height / factor); + font.SetSize(100 * min_c(widthFactor, heightFactor)); +} + + +void +SudokuView::_DrawKeyboardFocus() +{ + BRect frame = _Frame(fKeyboardX, fKeyboardY); + SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); + StrokeRect(frame); + frame.InsetBy(-1, -1); + StrokeRect(frame); + frame.InsetBy(2, 2); + StrokeRect(frame); +} + + +void +SudokuView::_DrawHints(uint32 x, uint32 y) +{ + bool showAll = fShowHintX == x && fShowHintY == y; + uint32 hintMask = fField->HintMaskAt(x, y); + if (hintMask == 0 && !showAll) + return; + + uint32 validMask = fField->ValidMaskAt(x, y); + BPoint leftTop = _LeftTop(x, y); + SetFont(&fHintFont); + + for (uint32 j = 0; j < fBlockSize; j++) { + for (uint32 i = 0; i < fBlockSize; i++) { + uint32 value = j * fBlockSize + i; + if ((hintMask & (1UL << value)) != 0) { + SetHighColor(kHintColor); + } else { + if (!showAll) + continue; + + if ((fHintFlags & kMarkValidHints) == 0 + || (validMask & (1UL << value)) != 0) + SetHighColor(110, 110, 80); + else + SetHighColor(180, 180, 120); + } + + char text[2]; + _SetText(text, value + 1); + DrawString(text, leftTop + BPoint((i + 0.5f) * fHintWidth + - StringWidth(text) / 2, floorf(j * fHintHeight) + + fHintBaseline)); + } + } +} diff --git a/src/apps/sudoku/SudokuView.h b/src/apps/sudoku/SudokuView.h index 0295704abd..5929fe5a41 100644 --- a/src/apps/sudoku/SudokuView.h +++ b/src/apps/sudoku/SudokuView.h @@ -40,7 +40,6 @@ public: virtual status_t Archive(BMessage* into, bool deep = true) const; static BArchivable* Instantiate(BMessage* archive); - void InitObject(const BMessage* archive); status_t SaveState(BMessage& state) const; @@ -84,6 +83,8 @@ protected: virtual void Draw(BRect updateRect); private: + void _InitObject(const BMessage* archive); + status_t _FilterString(const char* data, size_t dataLength, char* buffer, uint32& out, bool& ignore); @@ -101,28 +102,28 @@ private: uint32 y = UINT32_MAX); void _InvalidateKeyboardFocus(uint32 x, uint32 y); void _InsertKey(char rawKey, int32 modifiers); - void _SetValueHintValue(uint32 value); - void _RemoveHint(); + bool _GetHintFieldFor(BPoint where, uint32 x, + uint32 y, uint32& hintX, uint32& hintY); + bool _GetFieldFor(BPoint where, uint32& x, + uint32& y); void _ToggleValue(uint32 x, uint32 y, uint32 value, uint32 field); void _ToggleHintValue(uint32 x, uint32 y, uint32 hintX, uint32 hintY, uint32 value, uint32 field); - bool _GetHintFieldFor(BPoint where, uint32 x, - uint32 y, uint32& hintX, uint32& hintY); - bool _GetFieldFor(BPoint where, uint32& x, - uint32& y); - void _FitFont(BFont& font, float width, - float height); - void _DrawKeyboardFocus(); - void _DrawHints(uint32 x, uint32 y); - void _UndoRedo(BObjectList& undos, - BObjectList& redos); - void _PushUndo(); void _SetAllHints(); void _Solve(); void _SolveSingle(); bool _GetSolutions(SudokuSolver& solver); + void _UndoRedo(BObjectList& undos, + BObjectList& redos); + void _PushUndo(); + void _SetValueHintValue(uint32 value); + void _RemoveHint(); + void _FitFont(BFont& font, float width, + float height); + void _DrawKeyboardFocus(); + void _DrawHints(uint32 x, uint32 y); private: rgb_color fBackgroundColor;