diff options
Diffstat (limited to 'menu.cpp')
-rw-r--r-- | menu.cpp | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/menu.cpp b/menu.cpp new file mode 100644 index 0000000..2a4e422 --- /dev/null +++ b/menu.cpp @@ -0,0 +1,244 @@ +/* + * Sudoku: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menu.cpp 11 2005-10-28 01:00:01Z tom $ + */ + +#include "menu.h" +#include "puzzle.h" +#include "setup.h" +#include "bitmap.h" +#include "i18n.h" +#include <vdr/config.h> +#include <vdr/osdbase.h> +#include <vdr/osd.h> +#include <vdr/font.h> + +// Compatibility to older vdr versions +#if VDRVERSNUM < 10307 + #define tColor eDvbColor + #define DrawRectangle Fill + #define DrawBitmap SetBitmap + #define cOsdProvider cOsd + #define NewOsd OpenRaw + struct tArea { int x1, y1, x2, y2, bpp; }; + #define SetAreas(a,n) Create(a->x1, a->y1,\ + a->x2 - a->x1 + 1, a->y2 - a->y1 + 1,\ + a->bpp, true) + #define Color GetColor + #define savePalette(bitmap) savePalette(2) + #define SetPalette(palette, area) Width('X') +#endif + +using namespace SudokuPlugin; +using namespace Sudoku; + + +// Definitions for grid structure +#define CELL_SIZE 42 +#define CELL_POS(i) ((i) * (CELL_SIZE + 2) + (i)/RDIM * 3 + 5) +#define GRID_SIZE (DIM * (CELL_SIZE + 2) + DIM/RDIM * 3 + 5) + +// Definitions for grid colors +#define TRANS(c,t) tColor(((c) & 0x00FFFFFF) | (0xFF * (100-(t))/100)<<24) +#define GRID_COLOR clrWhite +#define CURSUR_COLOR clrBlue +#define NUMBER_FG clrWhite +#define NUMBER_BG clrBlack +#define ERROR_FG clrWhite +#define ERROR_BG clrRed +#define AMBIG_FG clrWhite +#define AMBIG_BG clrMagenta +#define MARKED_FG clrWhite +#define MARKED_BG clrGreen +#define GIVEN_FG clrBlack +#define GIVEN_BG clrCyan + + +//--- class SudokuPlugin::Menu ------------------------------------------------- + +/** Constructor */ +Menu::Menu(const SetupData& setup, Puzzle& puzzle, Pos& curr) : + cOsdObject(true), setup(setup), puzzle(puzzle), curr(curr) +{ + xPos = (720 - GRID_SIZE) / 2; + yPos = (576 - GRID_SIZE) / 2; + osd = NULL; + info = NULL; + infoText = NULL; + new_puzzle_request = false; +} + +/** Destructor */ +Menu::~Menu() +{ + delete info; + delete osd; +} + +/** Display the menu on the OSD. */ +void Menu::Show() +{ + int x1 = xPos, y1 = yPos; + int x2 = xPos + GRID_SIZE - 1, y2 = yPos + GRID_SIZE -1; + + osd = cOsdProvider::NewOsd(0, 0); + if (osd) + { + tArea areas[] = { x1, y1, x2, y2, 4 }; + osd->SetAreas(areas, 1); + paint(); + } +} + +/** Process user events. */ +eOSState Menu::ProcessKey(eKeys key) +{ + eOSState state = cOsdObject::ProcessKey(key); + if (state == osUnknown) + { + if (key == kBack) + return osEnd; + if (new_puzzle_request) + { + if (key == kOk) + { + new_puzzle_request = false; + puzzle.generate(setup.givens_count, setup.symmetric); + } + } + else + { + switch (key) + { + case kLeft: + case kLeft|k_Repeat: + curr = curr.prev_col(); + break; + case kRight: + case kRight|k_Repeat: + curr = curr.next_col(); + break; + case kUp: + case kUp|k_Repeat: + curr = curr.prev_row(); + break; + case kDown: + case kDown|k_Repeat: + curr = curr.next_row(); + break; + case k0: + case k1: + case k2: + case k3: + case k4: + case k5: + case k6: + case k7: + case k8: + case k9: + puzzle.set(curr, key - k0); + break; + case kRed: + puzzle.set(curr, puzzle.next_number(curr)); + break; + case kGreen: + puzzle.toggle_mark(curr); + break; + case kYellow: + if (puzzle.next_free(curr) <= Pos::last()) + curr = puzzle.next_free(curr); + break; + case kBlue: + if (puzzle.untouched()) + puzzle.generate(setup.givens_count, setup.symmetric); + else + puzzle.reset(); + break; + default: + return osContinue; + } + } + if (puzzle.solved()) + { + new_puzzle_request = true; + infoText = tr("Congratulations!\nPress OK to start a new puzzle"); + } + paint(); + state = osContinue; + } + return state; +} + +/** Paint all pieces of the menu. */ +void Menu::paint() +{ + int trans = setup.transparency; + tColor fg, bg = TRANS(GRID_COLOR, trans); + int x1 = xPos, y1 = yPos; + int x2 = xPos + GRID_SIZE - 1, y2 = yPos + GRID_SIZE -1; + + // Save and restore palette to reduce flickering. + cPalette savePalette(*osd->GetBitmap(0)); + osd->DrawRectangle(x1, y1, x2, y2, bg); + osd->SetPalette(savePalette, 0); + + // Paint all cells. + for (Pos p = Pos::first(); p <= Pos::last(); p = p.next()) + { + fg = NUMBER_FG, bg = NUMBER_BG; + if (puzzle.given(p)) + fg = GIVEN_FG, bg = GIVEN_BG; + else if (puzzle.marked(p)) + fg = MARKED_FG, bg = MARKED_BG; + else if (setup.mark_errors && puzzle.error(p)) + fg = ERROR_FG, bg = ERROR_BG; + else if (setup.mark_ambiguous && puzzle.ambiguous(p)) + fg = AMBIG_FG, bg = AMBIG_BG; + fg = TRANS(fg, trans); + bg = TRANS(bg, trans); + + // Paint the background of the cell. + x1 = xPos + CELL_POS(p.col()), y1 = yPos + CELL_POS(p.row()); + x2 = x1 + CELL_SIZE - 1, y2 = y1 + CELL_SIZE - 1; + osd->DrawRectangle(x1, y1, x2, y2, bg); + + // Paint the content of the cell. + if (puzzle.get(p) != 0) + { + char txt[2] = { '0' + puzzle.get(p), 0 }; +#if VDRVERSNUM < 10307 + osd->SetFont(fontFix); + osd->Text(x1 + max((CELL_SIZE - osd->Width(txt)) / 2, 0), + y1 + max((CELL_SIZE - cOsd::LineHeight()) / 2, 0), + txt, fg, bg); +#else + const cFont* font = cFont::GetFont(fontFix); + osd->DrawText(x1, y1, txt, fg, bg, font, CELL_SIZE, CELL_SIZE, taCenter); +#endif + } + } + + // Paint the cursor. + bg = TRANS(CURSUR_COLOR, trans); + x1 = xPos + CELL_POS(curr.col()), y1 = yPos + CELL_POS(curr.row()); + x2 = x1 + CELL_SIZE - 1, y2 = y1 + CELL_SIZE - 1; + osd->DrawRectangle(x1 - 5, y1 - 5, x2, y1, bg); + osd->DrawRectangle(x1 - 5, y1, x1, y2 + 5, bg); + osd->DrawRectangle(x1, y2, x2 + 5, y2 + 5, bg); + osd->DrawRectangle(x2, y1 - 5, x2 + 5, y2, bg); + + // Paint info window. + if (infoText) + { + if (!info) + info = new Bitmap(GRID_SIZE - 20, 60); + info->text(infoText); + osd->DrawBitmap(xPos + 10, yPos + 10, *info); + infoText = NULL; + } + + osd->Flush(); +} |