summaryrefslogtreecommitdiff
path: root/menu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'menu.cpp')
-rw-r--r--menu.cpp244
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();
+}