// -*-c++-*- //------------------------------------------------------------------------------ // xword - (http://xword.sourceforge.net) // Copyright 2001 Patrick Crosby //------------------------------------------------------------------------------ // GridWidget.cpp // // $Id: GridWidget.cpp,v 1.15 2002/01/23 19:43:03 pcrosby Exp $ //------------------------------------------------------------------------------ // This program is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software // Foundation; either version 2 of the License, or (at your option) any later // version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // You should have received a copy of the GNU General Public License along with // this program; if not, write to the Free Software Foundation, Inc., 59 Temple // Place, Suite 330, Boston, MA 02111-1307 USA //------------------------------------------------------------------------------ #include "GridWidget.h" #include #include #include #include "Error.h" //------------------------------------------------------------------------------ #include "Namespace.h" using namespace std; NAMESPACE_OPEN //------------------------------------------------------------------------------ const int GridWidget::s_nGridSize = 20; const int GridWidget::s_nBackColorRed = 35723; const int GridWidget::s_nBackColorGreen = 39321; const int GridWidget::s_nBackColorBlue = 40092; const int GridWidget::s_nOffset = 10; //------------------------------------------------------------------------------ GridWidget::GridWidget() : m_nSizeX(0), m_nSizeY(0), m_nCursorX(0), m_nCursorY(0), m_bAcross(true), m_pPuzzle(NULL) { size(s_nGridSize * 10 + s_nOffset * 2, s_nGridSize * 10 + s_nOffset * 2); add_events(GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK); } //------------------------------------------------------------------------------ GridWidget::~GridWidget() { } //------------------------------------------------------------------------------ gint GridWidget::expose_event_impl(GdkEventExpose* pEvent) { Draw(); return 0; // ??? } //------------------------------------------------------------------------------ gint GridWidget::key_press_event_impl(GdkEventKey* pEvent) { bool bMove = false; if (pEvent->state & GDK_CONTROL_MASK) { if (pEvent->keyval == GDK_Left) { if (PrevClue(true)) { bMove = true; } } else if (pEvent->keyval == GDK_Right) { if (NextClue(true)) { bMove = true; } } else if (pEvent->keyval == GDK_Up) { if (PrevClue(false)) { bMove = true; } } else if (pEvent->keyval == GDK_Down) { if (NextClue(false)) { bMove = true; } } } else { if (pEvent->keyval == GDK_Left) { if (m_bAcross) { if (MoveLeft(false)) { bMove = true; } } else { bMove = true; } m_bAcross = true; } else if (pEvent->keyval == GDK_Right) { if (m_bAcross) { if (MoveRight(false)) { bMove = true; } } else { bMove = true; } m_bAcross = true; } else if (pEvent->keyval == GDK_Up) { if (!m_bAcross) { if (MoveUp(false)) { bMove = true; } } else { bMove = true; } m_bAcross = false; } else if (pEvent->keyval == GDK_Down) { if (!m_bAcross) { if (MoveDown(false)) { bMove = true; } } else { bMove = true; } m_bAcross = false; } else if (pEvent->keyval == GDK_Home) { m_nCursorX = 0; m_nCursorY = 0; bMove = true; } else if (pEvent->keyval == GDK_End) { m_nCursorX = m_nSizeX - 1; m_nCursorY = m_nSizeY - 1; bMove = true; } else if (pEvent->keyval >= 0x41 && pEvent->keyval <= 0x7a) { if (pEvent->keyval <=0x5a) { // m_vecLetters[m_nCursorY][m_nCursorX] = pEvent->keyval; AssertNotNull(m_pPuzzle); m_pPuzzle->SetLetter(m_nCursorY, m_nCursorX, pEvent->keyval); } else if (pEvent->keyval >= 0x61) { // m_vecLetters[m_nCursorY][m_nCursorX] = pEvent->keyval - 0x61 + 0x41; AssertNotNull(m_pPuzzle); m_pPuzzle->SetLetter(m_nCursorY, m_nCursorX, pEvent->keyval - 0x61 + 0x41); } else { return 0; } if (m_bAcross) { if (MoveRight(true)) { bMove = true; } } else { if (MoveDown(true)) { bMove = true; } } Draw(); } else if (pEvent->keyval == GDK_BackSpace) { AssertNotNull(m_pPuzzle); m_pPuzzle->SetLetter(m_nCursorY, m_nCursorX, ' '); // m_vecLetters[m_nCursorY][m_nCursorX] = ' '; if (m_bAcross) { if (MoveLeft(false)) { bMove = true; } } else { if (MoveUp(false)) { bMove = true; } } Draw(); } else if (pEvent->keyval == GDK_Delete) { // m_vecLetters[m_nCursorY][m_nCursorX] = ' '; AssertNotNull(m_pPuzzle); m_pPuzzle->SetLetter(m_nCursorY, m_nCursorX, ' '); Draw(); } } if (bMove) { Draw(); CursorMoved(); } return 1; } //------------------------------------------------------------------------------ gint GridWidget::button_press_event_impl(GdkEventButton* pEvent) { AssertNotNull(m_pPuzzle); int nX = (int)pEvent->x - s_nOffset; int nY = (int)pEvent->y - s_nOffset; cout << "button press: (" << nX << ", " << nY << ")" << endl; nX = nX / s_nGridSize; nY = nY / s_nGridSize; if (nX < 0) { nX = 0; } if (nY < 0) { nY = 0; } if (nX >= m_nSizeX) { nX = m_nSizeX - 1; } if (nY >= m_nSizeY) { nY = m_nSizeY - 1; } cout << "button press grid: (" << nX << ", " << nY << ")" << endl; if (m_pPuzzle->GetGrid()[nY][nX].GetType() != Square::SOLID) { m_nCursorX = nX; m_nCursorY = nY; Draw(); CursorMoved(); } return 1; } //------------------------------------------------------------------------------ void GridWidget::SetGrid(/*const Puzzle::SquareGrid& grid*/) { // m_Grid = grid; AssertNotNull(m_pPuzzle); m_nSizeY = m_pPuzzle->GetGrid().size(); m_nSizeX = m_pPuzzle->GetGrid()[0].size(); size(s_nGridSize * m_nSizeX + s_nOffset * 2, s_nGridSize * m_nSizeY + s_nOffset * 2); set_usize(s_nGridSize * m_nSizeX + s_nOffset * 2, s_nGridSize * m_nSizeY + s_nOffset * 2); /* m_vecLetters.clear(); for (int i = 0; i < m_nSizeY; i++) { std::string s; for (int j = 0; j < m_nSizeX; j++) { // s.push_back(' '); s.push_back(' '); } m_vecLetters.push_back(s); } */ Draw(); CursorMoved(); } //------------------------------------------------------------------------------ void GridWidget::SetPuzzle(Puzzle* pPuzzle) { m_pPuzzle = pPuzzle; m_nCursorX = 0; m_nCursorY = 0; SetGrid(); Draw(); CursorMoved(); } //------------------------------------------------------------------------------ int GridWidget::GetWidth() const { return s_nGridSize * m_nSizeX + s_nOffset * 2; } //------------------------------------------------------------------------------ int GridWidget::GetHeight() const { return s_nGridSize * m_nSizeY + s_nOffset * 2; } //------------------------------------------------------------------------------ void GridWidget::Draw() { m_pixBack.create(get_window(), get_window().width(), get_window().height()); Gdk_GC gc; gc.create(m_pixBack); SetColor(gc, s_nBackColorRed, s_nBackColorGreen, s_nBackColorBlue); m_pixBack.draw_rectangle(gc, true, GetCenterX(), GetCenterY(), GetMaxX(), GetMaxY()); m_pixBack.draw_rectangle(this->get_style()->get_black_gc(), false, GetCenterX(), GetCenterY(), GetMaxX() - 1, GetMaxY() - 1); DrawGrid(); DrawCursor(); DrawLetters(); gc.create(get_window()); get_window().draw_pixmap(gc, m_pixBack, 0, 0, 0, 0); } //------------------------------------------------------------------------------ void GridWidget::DrawGrid() { AssertNotNull(m_pPuzzle); Gdk_GC gc = this->get_style()->get_black_gc(); int nCenterX = GetCenterX(); int nCenterY = GetCenterY(); std::string strClue; int nCursorClue = 0; // if (m_pPuzzle != NULL) { m_pPuzzle->GetClue(m_nCursorX, m_nCursorY, m_bAcross, strClue, nCursorClue); // } // for (unsigned int nRow = 0; nRow < m_Grid.size(); nRow++) { for (int nRow = 0; nRow < m_nSizeY; nRow++) { // for (unsigned int nCol = 0; nCol < m_Grid[nRow].size(); nCol++) { for (int nCol = 0; nCol < m_nSizeX; nCol++) { int nX = nCenterX + s_nOffset + s_nGridSize * nCol; int nY = nCenterY + s_nOffset + s_nGridSize * nRow; if (m_pPuzzle->GetGrid()[nRow][nCol].GetType() == Square::BLANK) { Gdk_GC gcBack = this->get_style()->get_white_gc(); // if (m_pPuzzle != NULL) { int nClue = -1; m_pPuzzle->GetClue(nCol, nRow, m_bAcross, strClue, nClue); if (nClue == nCursorClue) { gcBack.create(get_window()); SetColor(gcBack, 40000, 40000, 40000); } //} m_pixBack.draw_rectangle(gcBack, true, nX, nY, s_nGridSize, s_nGridSize); m_pixBack.draw_rectangle(gc, false, nX, nY, s_nGridSize, s_nGridSize); } else { m_pixBack.draw_rectangle(gc, true, nX, nY, s_nGridSize + 1, s_nGridSize + 1); } } } } //------------------------------------------------------------------------------ void GridWidget::DrawCursor() { Gdk_GC gc; gc.create(get_window()); SetColor(gc, 40000, 0, 0); int nCenterX = GetCenterX(); int nCenterY = GetCenterY(); int nX = nCenterX + s_nOffset + s_nGridSize * m_nCursorX + 1; int nY = nCenterY + s_nOffset + s_nGridSize * m_nCursorY + 1; m_pixBack.draw_rectangle(gc, true, nX, nY, s_nGridSize - 1, s_nGridSize - 1); } //------------------------------------------------------------------------------ void GridWidget::DrawLetters() { AssertNotNull(m_pPuzzle); Gdk_GC gc = this->get_style()->get_black_gc(); Gdk_Font font; GetFont(font); for (int nRow = 0; nRow < m_nSizeY; nRow++) { std::string strRow; // if (m_pPuzzle != NULL) { strRow = m_pPuzzle->GetLetterRow(nRow); // } for (int nCol = 0; nCol < m_nSizeX; nCol++) { if (m_pPuzzle->GetGrid()[nRow][nCol].GetType() == Square::BLANK) { char strChar[2]; strChar[0] = strRow[nCol]; strChar[1] = '\0'; int nFontWidth = font.string_width(strChar); int nFontHeight = font.string_height(strChar); int nX = GetCenterX() + s_nOffset + s_nGridSize * nCol; int nY = GetCenterY() + s_nOffset + s_nGridSize * nRow; nX += (s_nGridSize - nFontWidth) / 2 + 1; nY += (s_nGridSize - nFontHeight) / 2 + nFontHeight + 1; m_pixBack.draw_string(font, gc, nX, nY, strChar); } } } } //------------------------------------------------------------------------------ void GridWidget::SetColor(Gdk_GC& gc, int nRed, int nGreen, int nBlue) { Gdk_Color color; Gdk_Colormap colormap(Gdk_Colormap::get_system()); color.set_red(nRed); color.set_green(nGreen); color.set_blue(nBlue); colormap.alloc(color); gc.set_foreground(color); } //------------------------------------------------------------------------------ void GridWidget::GetFont(Gdk_Font& font) { font.create("-*-verdana-medium-r-*--*-80-*-*-*-*-*-*"); if (font.gdkobj() == NULL) { font.create("-*-arial-medium-r-*--*-80-*-*-*-*-*-*"); if (font.gdkobj() == NULL) { font.create("-*-*-medium-r-*--*-80-*-*-*-*-*-*"); if (font.gdkobj() == NULL) { font.create("-*-*-*-*-*--*-80-*-*-*-*-*-*"); if (font.gdkobj() == NULL) { font.create("-*-*-*-*-*--*-*-*-*-*-*-*-*"); } } } } } //------------------------------------------------------------------------------ int GridWidget::GetCenterX() { return (width() - GetMaxX()) / 2; } //------------------------------------------------------------------------------ int GridWidget::GetCenterY() { // int nMaxY = s_nOffset * 2 + s_nGridSize * m_nSizeY; return 0; } //------------------------------------------------------------------------------ int GridWidget::GetMaxX() { return s_nOffset * 2 + s_nGridSize * m_nSizeX; } //------------------------------------------------------------------------------ int GridWidget::GetMaxY() { return s_nOffset * 2 + s_nGridSize * m_nSizeY; } //------------------------------------------------------------------------------ bool GridWidget::MoveRight(bool bBlank) { AssertNotNull(m_pPuzzle); bool bResult = false; int nTempX = m_nCursorX + 1; while (nTempX < m_nSizeX && m_pPuzzle->IsFull(m_nCursorY, nTempX, bBlank)) { nTempX++; } if (nTempX < m_nSizeX) { m_nCursorX = nTempX; bResult = true; } return bResult; } //------------------------------------------------------------------------------ bool GridWidget::MoveLeft(bool bBlank) { AssertNotNull(m_pPuzzle); bool bResult = false; int nTempX = m_nCursorX - 1; while (nTempX >= 0 && m_pPuzzle->IsFull(m_nCursorY, nTempX, bBlank)) { nTempX--; } if (nTempX >= 0) { m_nCursorX = nTempX; bResult = true; } return bResult; } //------------------------------------------------------------------------------ bool GridWidget::MoveDown(bool bBlank) { AssertNotNull(m_pPuzzle); bool bResult = false; int nTempY = m_nCursorY + 1; while (nTempY < m_nSizeY && m_pPuzzle->IsFull(nTempY, m_nCursorX, bBlank)) { nTempY++; } if (nTempY < m_nSizeY) { m_nCursorY = nTempY; bResult = true; } return bResult; } //------------------------------------------------------------------------------ bool GridWidget::MoveUp(bool bBlank) { AssertNotNull(m_pPuzzle); bool bResult = false; int nTempY = m_nCursorY - 1; while (nTempY >= 0 && m_pPuzzle->IsFull(nTempY, m_nCursorX, bBlank)) { nTempY--; } if (nTempY >= 0) { m_nCursorY = nTempY; bResult = true; } return bResult; } //------------------------------------------------------------------------------ bool GridWidget::PrevClue(bool bAcross) { AssertNotNull(m_pPuzzle); bool bResult = false; std::string strClue; int nCursorClue = 0; m_pPuzzle->GetClue(m_nCursorX, m_nCursorY, bAcross, strClue, nCursorClue); nCursorClue--; while (nCursorClue > 0 && bResult == false) { // get clue position from puzzle int nY = m_pPuzzle->GetClueRow(nCursorClue, bAcross); int nX = m_pPuzzle->GetClueCol(nCursorClue, bAcross); if (nY != -1 && nX != -1) { m_nCursorY = nY; m_nCursorX = nX; m_bAcross = bAcross; bResult = true; } nCursorClue--; } return bResult; } //------------------------------------------------------------------------------ bool GridWidget::NextClue(bool bAcross) { AssertNotNull(m_pPuzzle); bool bResult = false; std::string strClue; int nCursorClue = 0; m_pPuzzle->GetClue(m_nCursorX, m_nCursorY, bAcross, strClue, nCursorClue); nCursorClue++; while (nCursorClue < m_pPuzzle->GetMaxClueNum() && bResult == false) { // get clue position from puzzle int nY = m_pPuzzle->GetClueRow(nCursorClue, bAcross); int nX = m_pPuzzle->GetClueCol(nCursorClue, bAcross); if (nY != -1 && nX != -1) { m_nCursorY = nY; m_nCursorX = nX; m_bAcross = bAcross; bResult = true; } nCursorClue++; } return bResult; } //------------------------------------------------------------------------------ NAMESPACE_CLOSE //------------------------------------------------------------------------------