<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>icons/16x16/zoom-in.png</filename>
    </added>
    <added>
      <filename>icons/16x16/zoom-out.png</filename>
    </added>
    <added>
      <filename>icons/22x22/zoom-in.png</filename>
    </added>
    <added>
      <filename>icons/22x22/zoom-out.png</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,6 @@
+2009-06-20 Graeme Gott &lt;graeme@gottcode.org&gt;
+	* Add zoom support.
+
 2009-03-16 Graeme Gott &lt;graeme@gottcode.org&gt;
 	* Use only one scoreboard.
 </diff>
      <filename>ChangeLog</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,8 @@
 	&lt;file&gt;16x16/games-highscores.png&lt;/file&gt;
 	&lt;file&gt;16x16/games-hint.png&lt;/file&gt;
 	&lt;file&gt;16x16/media-playback-pause.png&lt;/file&gt;
+	&lt;file&gt;16x16/zoom-in.png&lt;/file&gt;
+	&lt;file&gt;16x16/zoom-out.png&lt;/file&gt;
 
 	&lt;file&gt;22x22/application-exit.png&lt;/file&gt;
 	&lt;file&gt;22x22/document-new.png&lt;/file&gt;
@@ -15,5 +17,7 @@
 	&lt;file&gt;22x22/games-highscores.png&lt;/file&gt;
 	&lt;file&gt;22x22/games-hint.png&lt;/file&gt;
 	&lt;file&gt;22x22/media-playback-pause.png&lt;/file&gt;
+	&lt;file&gt;22x22/zoom-in.png&lt;/file&gt;
+	&lt;file&gt;22x22/zoom-out.png&lt;/file&gt;
 &lt;/qresource&gt;
 &lt;/RCC&gt;</diff>
      <filename>icons/icons.qrc</filename>
    </modified>
    <modified>
      <diff>@@ -49,6 +49,9 @@ Board::Board(QMainWindow* parent)
 	m_smooth_movement(true),
 	m_col_delta(0),
 	m_row_delta(0),
+	m_zoom(5),
+	m_max_zoom(5),
+	m_zoom_size(14),
 	m_player_angle(360),
 	m_player_steps(0),
 	m_player_total_time(0),
@@ -88,6 +91,8 @@ Board::Board(QMainWindow* parent)
 	// Setup theme support
 	m_theme = new Theme;
 
+	loadSettings();
+
 	// Start or load game
 	if (QSettings().contains(&quot;Current/Seed&quot;)) {
 		loadGame();
@@ -95,8 +100,6 @@ Board::Board(QMainWindow* parent)
 		m_done = true;
 		newGame();
 	}
-
-	loadSettings();
 }
 
 // ============================================================================
@@ -261,7 +264,30 @@ void Board::hint()
 		} else {
 			m_hint_angle = 180;
 		}
-		m_hint = m_hint - m_player + QPoint(3,3);
+		int pos = (m_zoom / 2) + 1;
+		m_hint = m_hint - m_player + QPoint(pos, pos);
+		update();
+	}
+}
+
+// ============================================================================
+
+void Board::zoomIn()
+{
+	if (m_zoom &gt; 5) {
+		m_zoom -= 2;
+		scale();
+		update();
+	}
+}
+
+// ============================================================================
+
+void Board::zoomOut()
+{
+	if (m_zoom &lt; m_max_zoom) {
+		m_zoom += 2;
+		scale();
 		update();
 	}
 }
@@ -272,6 +298,13 @@ void Board::loadSettings()
 {
 	QSettings settings;
 
+	// Load zoom
+	m_zoom = QSettings().value(&quot;Zoom&quot;, 5).toInt();
+	if ((m_zoom % 2) == 0) {
+		m_zoom--;
+	}
+	m_zoom = qMax(m_zoom, 5);
+
 	// Load gameplay settings
 #if !defined(QTOPIA_PHONE)
 	m_status_steps_message-&gt;setVisible(settings.value(&quot;Show Steps&quot;, true).toBool());
@@ -405,11 +438,7 @@ void Board::paintEvent(QPaintEvent*)
 
 void Board::resizeEvent(QResizeEvent*)
 {
-	int size = qMin(width(), height());
-	size -= (size % 14);
-	float scale = static_cast&lt;float&gt;(size) / 448.0f;
-	m_unit = scale * 32;
-	m_theme-&gt;scale(m_unit);
+	scale();
 }
 
 // ============================================================================
@@ -439,11 +468,29 @@ void Board::updateStatusMessage()
 
 // ============================================================================
 
+void Board::scale()
+{
+	m_zoom_size = (m_zoom * 3) - 1;
+	m_unit = qMin(width(), height()) / m_zoom_size;
+	m_theme-&gt;scale(m_unit);
+	emit zoomOutAvailable(m_zoom &lt; m_max_zoom);
+	emit zoomInAvailable(m_zoom &gt; 5);
+	QSettings().setValue(&quot;Zoom&quot;, m_zoom);
+}
+
+// ============================================================================
+
 void Board::generate(unsigned int seed)
 {
 	QSettings settings;
 	int size = qBound(10, settings.value(&quot;Current/Size&quot;).toInt(), 100);
 	m_total_targets = qBound(1, settings.value(&quot;Current/Targets&quot;).toInt(), 100);
+	m_max_zoom = size / 2;
+	if ((m_max_zoom % 2) == 0) {
+		m_max_zoom--;
+	}
+	m_zoom = qMin(m_zoom, m_max_zoom);
+	scale();
 
 	// Create new maze
 	m_targets.clear();
@@ -530,8 +577,11 @@ void Board::finish()
 
 void Board::renderMaze(int frame)
 {
-	int column = m_player.x() - m_col_delta - 3;
-	int row = m_player.y() - m_row_delta - 3;
+	int pos = (m_zoom / 2) + 1;
+	int full_view = m_zoom + 3;
+
+	int column = m_player.x() - m_col_delta - pos;
+	int row = m_player.y() - m_row_delta - pos;
 	int columns = m_maze-&gt;columns();
 	int rows = m_maze-&gt;rows();
 
@@ -544,7 +594,7 @@ void Board::renderMaze(int frame)
 
 	// Create painter
 	QPainter painter(this);
-	int size = m_unit * 14;
+	int size = m_unit * m_zoom_size;
 	painter.setClipRect((width() - size) &gt;&gt; 1, (height() - size) &gt;&gt; 1, size, size);
 	painter.translate((width() - size) &gt;&gt; 1, (height() - size) &gt;&gt; 1);
 	painter.translate(-3 * m_unit, -3 * m_unit);
@@ -558,35 +608,35 @@ void Board::renderMaze(int frame)
 	painter.translate(delta * m_col_delta, delta * m_row_delta);
 
 	// Draw background
-	for (int r = 0; r &lt; 8; ++r) {
-		for (int c = 0; c &lt; 8; ++c) {
+	for (int r = 0; r &lt; full_view; ++r) {
+		for (int c = 0; c &lt; full_view; ++c) {
 			m_theme-&gt;draw(painter, c, r, Theme::Background);
 		}
 	}
 
 	// Initialize corners
-	unsigned char corners[8][8];
-	for (int r = 0; r &lt; 8; ++r) {
-		for (int c = 0; c &lt; 8; ++c) {
+	unsigned char corners[full_view][full_view];
+	for (int r = 0; r &lt; full_view; ++r) {
+		for (int c = 0; c &lt; full_view; ++c) {
 			corners[c][r] = 0;
 		}
 	}
 
 	// Setup columns
 	int column_start = 0;
-	int column_count = 7;
+	int column_count = m_zoom + 2;
 	if (column &lt; 1) {
 		column_start = abs(column);
-	} else if (column + 6 &gt;= columns) {
+	} else if ((column + m_zoom + 1) &gt;= columns) {
 		column_count = columns - column;
 	}
 
 	// Setup rows
 	int row_start = 0;
-	int row_count = 7;
+	int row_count = m_zoom + 2;
 	if (row &lt; 1) {
 		row_start = abs(row);
-	} else if (row + 6 &gt;= rows) {
+	} else if ((row + m_zoom + 1) &gt;= rows) {
 		row_count = rows - row;
 	}
 
@@ -641,8 +691,8 @@ void Board::renderMaze(int frame)
 	}
 
 	// Draw corners
-	for (int r = 0; r &lt; 8; ++r) {
-		for (int c = 0; c &lt; 8; ++c) {
+	for (int r = 0; r &lt; full_view; ++r) {
+		for (int c = 0; c &lt; full_view; ++c) {
 			unsigned char walls = corners[c][r];
 			if (walls) {
 				m_theme-&gt;drawCorner(painter, c, r, walls);
@@ -651,7 +701,7 @@ void Board::renderMaze(int frame)
 	}
 
 	// Draw start
-	QRect view(column, row, 7, 7);
+	QRect view(column, row, m_zoom + 2, m_zoom + 2);
 	if (view.contains(m_start)) {
 		m_theme-&gt;draw(painter, m_start.x() - column, m_start.y() - row, Theme::Start);
 	}
@@ -689,7 +739,7 @@ void Board::renderMaze(int frame)
 	}
 
 	// Draw player
-	m_theme-&gt;draw(painter, 3, 3, Theme::Player, m_player_angle);
+	m_theme-&gt;draw(painter, pos, pos, Theme::Player, m_player_angle);
 }
 
 // ============================================================================
@@ -746,7 +796,7 @@ void Board::renderPause()
 {
 	// Create painter
 	QPainter painter(this);
-	int size = m_unit * 14;
+	int size = m_unit * m_zoom_size;
 	painter.translate((width() - size) &gt;&gt; 1, (height() - size) &gt;&gt; 1);
 	painter.fillRect(0, 0, size, size, Qt::white);
 
@@ -760,7 +810,7 @@ void Board::renderText(QPainter* painter, const QString&amp; message) const
 {
 	painter-&gt;setFont(QFont(&quot;Sans&quot;, 24));
 	QRect rect = painter-&gt;fontMetrics().boundingRect(message);
-	int size = (m_unit * 14) &gt;&gt; 1;
+	int size = (m_unit * m_zoom_size) &gt;&gt; 1;
 	int x1 = size - ((rect.width() + rect.height()) &gt;&gt; 1);
 	int y1 = size - rect.height();
 	painter-&gt;setPen(Qt::NoPen);</diff>
      <filename>src/board.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -40,6 +40,8 @@ public:
 signals:
 	void pauseChecked(bool checked);
 	void pauseAvailable(bool run);
+	void zoomInAvailable(bool available);
+	void zoomOutAvailable(bool available);
 	void finished(int seconds, int steps, int algorithm, int size);
 
 public slots:
@@ -48,6 +50,8 @@ public slots:
 	void saveGame();
 	void pauseGame(bool paused);
 	void hint();
+	void zoomIn();
+	void zoomOut();
 	void loadSettings();
 
 protected:
@@ -60,6 +64,7 @@ private slots:
 	void updateStatusMessage();
 
 private:
+	void scale();
 	void generate(unsigned int seed);
 	void finish();
 	void renderMaze(int frame);
@@ -88,6 +93,9 @@ private:
 
 	Theme* m_theme;
 	int m_unit;
+	int m_zoom;
+	int m_max_zoom;
+	int m_zoom_size;
 
 	// Player
 	QPoint m_player;</diff>
      <filename>src/board.h</filename>
    </modified>
    <modified>
      <diff>@@ -35,6 +35,7 @@
 #include &lt;QSettings&gt;
 #include &lt;QString&gt;
 #include &lt;QTimer&gt;
+#include &lt;QWheelEvent&gt;
 
 #if defined(QTOPIA_PHONE)
 #include &lt;QSoftMenuBar&gt;
@@ -96,6 +97,18 @@ void Window::closeEvent(QCloseEvent* event)
 
 // ============================================================================
 
+void Window::wheelEvent(QWheelEvent* event)
+{
+	if (event-&gt;delta() &gt; 0) {
+		m_board-&gt;zoomIn();
+	} else {
+		m_board-&gt;zoomOut();
+	}
+	QMainWindow::wheelEvent(event);
+}
+
+// ============================================================================
+
 void Window::initActions()
 {
 #if defined(QTOPIA_PHONE)
@@ -142,6 +155,18 @@ void Window::initActions()
 	quit_icon.addPixmap(QPixmap(&quot;:/16x16/application-exit.png&quot;));
 	game_menu-&gt;addAction(quit_icon, tr(&quot;Quit&quot;), this, SLOT(close()), tr(&quot;Ctrl+Q&quot;));
 
+	QMenu* view_menu = menuBar()-&gt;addMenu(tr(&quot;View&quot;));
+
+	QIcon zoom_in_icon(QPixmap(&quot;:/22x22/zoom-in.png&quot;));
+	zoom_in_icon.addPixmap(QPixmap(&quot;:/16x16/zoom-in.png&quot;));
+	QAction* zoom_in_action = view_menu-&gt;addAction(zoom_in_icon, tr(&quot;Zoom In&quot;), m_board, SLOT(zoomIn()), tr(&quot;Ctrl++&quot;));
+	connect(m_board, SIGNAL(zoomInAvailable(bool)), zoom_in_action, SLOT(setEnabled(bool)));
+
+	QIcon zoom_out_icon(QPixmap(&quot;:/22x22/zoom-out.png&quot;));
+	zoom_out_icon.addPixmap(QPixmap(&quot;:/16x16/zoom-out.png&quot;));
+	QAction* zoom_out_action = view_menu-&gt;addAction(zoom_out_icon, tr(&quot;Zoom Out&quot;), m_board, SLOT(zoomOut()), tr(&quot;Ctrl+-&quot;));
+	connect(m_board, SIGNAL(zoomOutAvailable(bool)), zoom_out_action, SLOT(setEnabled(bool)));
+
 	QMenu* help_menu = menuBar()-&gt;addMenu(tr(&quot;Help&quot;));
 	help_menu-&gt;addAction(tr(&quot;About&quot;), this, SLOT(about()));
 	help_menu-&gt;addAction(tr(&quot;About &amp;Qt&quot;), qApp, SLOT(aboutQt()));
@@ -155,6 +180,9 @@ void Window::initActions()
 	toolbar-&gt;addAction(new_action);
 	toolbar-&gt;addAction(m_pause_action);
 	toolbar-&gt;addAction(m_hint_action);
+	toolbar-&gt;addSeparator();
+	toolbar-&gt;addAction(zoom_in_action);
+	toolbar-&gt;addAction(zoom_out_action);
 	addToolBar(toolbar);
 	setContextMenuPolicy(Qt::NoContextMenu);
 #endif</diff>
      <filename>src/window.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -34,6 +34,7 @@ public:
 
 protected:
 	virtual void closeEvent(QCloseEvent* event);
+	virtual void wheelEvent(QWheelEvent* event);
 
 private slots:
 	void about();</diff>
      <filename>src/window.h</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>57e7986dc6025e77df2882db8b60f1fecc794d05</id>
    </parent>
  </parents>
  <author>
    <name>Graeme Gott</name>
    <email>graeme@gottcode.org</email>
  </author>
  <url>http://github.com/gottcode/cutemaze/commit/bb942959579cd278308c318ac1e6e57383dd5e9c</url>
  <id>bb942959579cd278308c318ac1e6e57383dd5e9c</id>
  <committed-date>2009-06-29T05:10:32-07:00</committed-date>
  <authored-date>2009-06-20T15:18:17-07:00</authored-date>
  <message>Add zoom support.</message>
  <tree>5de242a361ae36334e8f0e3c12d4c7bdaf4f4ad7</tree>
  <committer>
    <name>Graeme Gott</name>
    <email>graeme@gottcode.org</email>
  </committer>
</commit>
