Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) RubiksClockWidget

 

STLQt CreatorLubuntu

 

RubiksClockWidget is a widget class for a RubiksClock.

Technical facts

 

 

 

 

 

 

./CppRubiksClockWidget/CppRubiksClockWidget.pri

 

INCLUDEPATH += \
    ../../Classes/CppRubiksClockWidget

SOURCES += \
    ../../Classes/CppRubiksClockWidget/rubiksclockdial.cpp \
    ../../Classes/CppRubiksClockWidget/rubiksclockdialwidget.cpp \
    ../../Classes/CppRubiksClockWidget/rubiksclockwidget.cpp

HEADERS  += \
    ../../Classes/CppRubiksClockWidget/rubiksclockdial.h \
    ../../Classes/CppRubiksClockWidget/rubiksclockdialwidget.h \
    ../../Classes/CppRubiksClockWidget/rubiksclockwidget.h

OTHER_FILES += \
    ../../Classes/CppRubiksClockWidget/Licence.txt

 

 

 

 

 

./CppRubiksClockWidget/rubiksclockdial.h

 

//---------------------------------------------------------------------------
/*
RubiksClockDial, class for displaying a Rubik's Clock Dial
Copyright (C) 2011-2015 Richel Bilderbeek

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 3 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, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRubiksClockWidget.htm
//---------------------------------------------------------------------------
#ifndef RUBIKSCLOCKDIAL_H
#define RUBIKSCLOCKDIAL_H

#include <iosfwd>
#include <string>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/checked_delete.hpp>
#include <boost/signals2.hpp>

#include "rubiksclockfwd.h"
#include "widget.h"
#pragma GCC diagnostic pop

namespace ribi {

struct Dial;

namespace ruco {

///ClockDial is a class to display a Rubik's Clock Dial
struct ClockDial : public Widget
{
  explicit ClockDial(
    const int time,
    const int x,
    const int y,
    const int width,
    const int height,
    const unsigned char red,
    const unsigned char green,
    const unsigned char blue);

  const Dial * GetDial() const noexcept { return m_dial.get(); }

  int GetTime() const noexcept { return m_time % 12; }

  ///Obtain this class its version
  static std::string GetVersion() noexcept;

  ///Obtain this class its version history
  static std::vector<std::string> GetVersionHistory() noexcept;

  ///Turn the dials n_positions_clockwise clockwise,
  ///negative values are also allowed
  void Turn(const int n_positions_clockwise) noexcept;

  private:
  //DialWidget can only be deleted by Boost smart pointers
  virtual ~ClockDial() noexcept {}
  friend void boost::checked_delete<>(ClockDial*);

  boost::scoped_ptr<Dial> m_dial;

  ///Denotes the time shown by the dial as in a clock
  int m_time;

  friend std::ostream& operator<<(std::ostream& os, const ClockDial& widget) noexcept;

  public:

  ///Obtain the angle in radians between two deltas
  ///12 o'clock is 0.0 * pi
  /// 3 o'clock is 0.5 * pi
  /// 6 o'clock is 1.0 * pi
  /// 9 o'clock is 1.5 * pi
  //From www.richelbilderbeek.nl/CppGetAngle.htm
  //static double GetAngle(const double dX, const double dY);

  //From www.richelbilderbeek.nl/CppGetDistance.htm
  static double GetDistance(const double dX, const double dY) noexcept;
};

std::ostream& operator<<(std::ostream& os, const ClockDial& widget) noexcept;

} //~namespace ruco
} //~namespace ribi

#endif // RUBIKSCLOCKDIAL_H

 

 

 

 

 

./CppRubiksClockWidget/rubiksclockdial.cpp

 

//---------------------------------------------------------------------------
/*
ClockDial, class for displaying a Rubik's Clock Dial
Copyright (C) 2011-2015 Richel Bilderbeek

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 3 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, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRubiksClockWidget.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include "rubiksclockdial.h"

#include <cassert>
#include <cmath>
#include <iostream>

#include <boost/numeric/conversion/cast.hpp>

#include "dial.h"

#include "trace.h"

#pragma GCC diagnostic pop

ribi::ruco::ClockDial::ClockDial(
  const int time,
  const int x,
  const int y,
  const int width,
  const int height,
  const unsigned char red,
  const unsigned char green,
  const unsigned char blue)
  : m_dial(new Dial(0.0,red,green,blue)),
    m_time(time + 1)
{
  assert(m_dial);
  SetGeometry(x,y,width,height);
  Turn(-1);
}

std::string ribi::ruco::ClockDial::GetVersion() noexcept
{
  return "1.2";
}

std::vector<std::string> ribi::ruco::ClockDial::GetVersionHistory() noexcept
{
  return {
    "2011-09-08: Version 1.0: initial version, called RubiksClockDial",
    "2014-01-23: Version 1.1: renamed to ClockDial",
    "2014-03-28: version 1.2: replaced Rect by Boost.Geometry its box class"
  };
}

void ribi::ruco::ClockDial::Turn(const int n_positions_clockwise) noexcept
{
  if (n_positions_clockwise % 12 != 0)
  {
    m_time += n_positions_clockwise;
    m_time %= 12;
    m_time += 12;
    m_time %= 12;
    assert(m_time >= 0);
    assert(m_time < 12);
    m_dial->SetPosition(boost::numeric_cast<double>(m_time) / 12.0);
  }
}

std::ostream& ribi::ruco::operator<<(std::ostream& os, const ClockDial& widget) noexcept
{
  os
    << "<ClockDial>"
    << *widget.m_dial
    //<< widget.GetGeometry()
    << "</ClockDial>";
  return os;
}

 

 

 

 

 

./CppRubiksClockWidget/rubiksclockdialwidget.h

 

//---------------------------------------------------------------------------
/*
RubiksClockDialWidget, class for displaying a RubiksClockDial
Copyright (C) 2011-2015 Richel Bilderbeek

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 3 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, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRubiksClockDialWidget.htm
//---------------------------------------------------------------------------
#ifndef RUBIKSCLOCKDIALWIDGET_H
#define RUBIKSCLOCKDIALWIDGET_H

#include <iosfwd>
#include <string>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/checked_delete.hpp>
#include <boost/signals2.hpp>
#include "rubiksclockfwd.h"
#include "widget.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace ruco {

///RubiksClockDialWidget is a class to display a RubiksClockDial
struct ClockDialWidget : public ::ribi::Widget
{
  explicit ClockDialWidget(
    const double position,
    const int x,
    const int y,
    const int width,
    const int height,
    const unsigned char red,
    const unsigned char green,
    const unsigned char blue);

        ClockDial * GetRubiksClockDial()       noexcept { return m_dial.get(); }
  const ClockDial * GetRubiksClockDial() const noexcept { return m_dial.get(); }

  static std::string GetVersion() noexcept;
  static std::vector<std::string> GetVersionHistory() noexcept;

  ///Is the dial clicked?
  bool IsClicked(const int x, const int y) const;

  private:
  //RubiksClockDialWidget can only be deleted by Boost smart pointers
  virtual ~ClockDialWidget() noexcept {}
  friend void boost::checked_delete<>(ClockDialWidget*);

  boost::scoped_ptr<ClockDial> m_dial;

  static double GetDistance(const double dX, const double dY);


  friend std::ostream& operator<<(std::ostream& os, const ClockDialWidget& widget);
};

std::ostream& operator<<(std::ostream& os, const ClockDialWidget& widget);

} //~namespace ruco
} //~namespace ribi

#endif // RUBIKSCLOCKDIALWIDGET_H

 

 

 

 

 

./CppRubiksClockWidget/rubiksclockdialwidget.cpp

 

//---------------------------------------------------------------------------
/*
RubiksClockDialWidget, class for displaying a RubiksClockDial
Copyright (C) 2011-2015 Richel Bilderbeek

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 3 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, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRubiksClockDialWidget.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include "rubiksclockdialwidget.h"

#include <cassert>
#include <cmath>

#include <iostream>

#include <boost/numeric/conversion/cast.hpp>

#include "dial.h"
#include "rubiksclockdial.h"

//#include "trace.h"

#pragma GCC diagnostic pop

ribi::ruco::ClockDialWidget::ClockDialWidget(
  const double position,
  const int x,
  const int y,
  const int width,
  const int height,
  const unsigned char red,
  const unsigned char green,
  const unsigned char blue)
  : m_dial(new ClockDial(position,x,y,width,height,red,green,blue))
{
  SetGeometry(x,y,width,height);
}

double ribi::ruco::ClockDialWidget::GetDistance(const double dX, const double dY)
{
  return std::sqrt( (dX * dX) + (dY * dY) );
}

std::string ribi::ruco::ClockDialWidget::GetVersion() noexcept
{
  return "1.2";
}

std::vector<std::string> ribi::ruco::ClockDialWidget::GetVersionHistory() noexcept
{
  return {
    "2011-09-08: Version 1.0: initial version, called 'RubiksClockDialWidget'",
    "2014-01-23: Version 1.1: renamed to 'ClockDialWidget'",
    "2014-03-28: version 1.2: replaced Rect by Boost.Geometry its box class"
  };
}

bool ribi::ruco::ClockDialWidget::IsClicked(const int x, const int y) const
{
  const double widget_midx
    = boost::numeric_cast<double>(GetLeft())
    + (boost::numeric_cast<double>(GetWidth()) / 2.0);
  const double widget_midy
    = boost::numeric_cast<double>(GetTop())
    + (boost::numeric_cast<double>(GetHeight()) / 2.0);
  const double x_d = boost::numeric_cast<double>(x);
  const double y_d = boost::numeric_cast<double>(y);
  return GetDistance(x_d - widget_midx, y_d - widget_midy)
    < (boost::numeric_cast<double>(GetWidth()) / 2.0);
}

std::ostream& ribi::ruco::operator<<(std::ostream& os, const ribi::ruco::ClockDialWidget& widget)
{
  os
    << "<RubiksClockDialWidget>"
    << *widget.m_dial
    //<< widget.GetGeometry()
    << "</RubiksClockDialWidget>";
  return os;
}

 

 

 

 

 

./CppRubiksClockWidget/rubiksclockwidget.h

 

//---------------------------------------------------------------------------
/*
RubiksClockWidget, class for displaying a RubiksClock
Copyright (C) 2011-2015 Richel Bilderbeek

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 3 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, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRubiksClockWidget.htm
//---------------------------------------------------------------------------
#ifndef RUBIKSCLOCKWIDGET_H
#define RUBIKSCLOCKWIDGET_H

#include <iosfwd>
#include <string>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/checked_delete.hpp>
#include <boost/signals2.hpp>
#include "rubiksclockfwd.h"
#include "widget.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace ruco {

///RubiksClockWidget is a class to display a RubiksClock
struct ClockWidget : public Widget
{
  explicit ClockWidget(
    const int x = 0,
    const int y = 0,
    const int width = 192,
    const int height = 192
  ) noexcept;

  ///Click on the RubiksClock by the left mouse button or another
  void Click(const int x, const int y,const bool button_left) noexcept;

  ///Flip the Rubik's Clock and display the other side
  void Flip() noexcept;

  ///Does the widget display the front side?
  bool GetDisplayFront() const noexcept { return m_display_front; }

        Clock * GetRubiksClock()       noexcept { return m_clock.get(); }
  const Clock * GetRubiksClock() const noexcept { return m_clock.get(); }
  static std::string GetVersion() noexcept;
  static std::vector<std::string> GetVersionHistory() noexcept;

  boost::shared_ptr<TextCanvas> ToTextCanvas() const noexcept;

  ///Respond to a change in the clock
  mutable boost::signals2::signal<void ()> m_signal_widget_flipped;

  private:
  //RubiksClockWidget can only be deleted by Boost smart pointers
  virtual ~ClockWidget() noexcept {}
  friend void boost::checked_delete<>(ClockWidget*);

  ///The RubiksClock
  boost::scoped_ptr<Clock> m_clock;

  ///Does this widget display the front or the back side?
  bool m_display_front;

  ///Respond to a change in geometry
  void OnResize() noexcept;

  friend std::ostream& operator<<(std::ostream& os, const ClockWidget& widget) noexcept;
};

std::ostream& operator<<(std::ostream& os, const ClockWidget& widget) noexcept;

} //~namespace ruco
} //~namespace ribi

#endif // RUBIKSCLOCKWIDGET_H

 

 

 

 

 

./CppRubiksClockWidget/rubiksclockwidget.cpp

 

//---------------------------------------------------------------------------
/*
RubiksClockWidget, class for displaying a RubiksClock
Copyright (C) 2011-2015 Richel Bilderbeek

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 3 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, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRubiksClockWidget.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include "rubiksclockwidget.h"

#include <cassert>
#include <cmath>

#include <iostream>

#include <boost/numeric/conversion/cast.hpp>

#include "dial.h"
#include "drawcanvas.h"
#include "rubiksclock.h"
#include "rubiksclocktimes.h"
#include "rubiksclockdial.h"
#include "rubiksclockdialwidget.h"
#include "rubiksclockpegs.h"
#include "textcanvas.h"
#include "togglebutton.h"
#include "togglebuttonwidget.h"
//#include "trace.h"

#pragma GCC diagnostic pop

ribi::ruco::ClockWidget::ClockWidget(
  const int x,
  const int y,
  const int width,
  const int height) noexcept
  : m_signal_widget_flipped{},
    m_clock{new Clock},
    m_display_front{true}
{
  m_signal_geometry_changed.connect(
    boost::bind(
      &ribi::ruco::ClockWidget::OnResize,
      this));

  SetGeometry(x,y,width,height);
}

void ribi::ruco::ClockWidget::Click(const int x,const int y,const bool button_left) noexcept
{
  const boost::shared_ptr<const Times> times = (m_display_front ? m_clock->GetFrontTimes() : m_clock->GetBackTimes());
  const boost::shared_ptr<const Pegs> pegs = m_clock->GetFrontPegs();

  for (int i=0; i!=2; ++i)
  {
    for (int j=0; j!=2; ++j)
    {
      if (times->times[i*2][j*2]->IsClicked(x,y))
      {
        if(m_display_front)
        {
          this->m_clock->TurnWheel(
            i
            ? (j ? Side::bottomRight : Side::topRight)
            : (j ? Side::bottomLeft : Side::topLeft),
            button_left ? 1 : -1);
        }
        else
        {
          this->m_clock->TurnWheel(
            i
            ? (j ? Side::bottomLeft : Side::topLeft)
            : (j ? Side::bottomRight : Side::topRight),
            button_left ? 1 : -1);
        }
      }
      else if (pegs->m_pegs[i][j]->IsIn(x,y))
      {
        m_clock->TogglePeg(
          i
          ? (j ? Side::bottomRight : Side::topRight)
          : (j ? Side::bottomLeft : Side::topLeft));
      }
    }
  }
}

void ribi::ruco::ClockWidget::Flip() noexcept
{
  m_display_front = !m_display_front;
  m_signal_widget_flipped();
}

std::string ribi::ruco::ClockWidget::GetVersion() noexcept
{
  return "1.4";
}

std::vector<std::string> ribi::ruco::ClockWidget::GetVersionHistory() noexcept
{
  return {
    "2011-09-01: Version 1.0: initial version",
    "2011-09-09: Version 1.1: use of geometries",
    "2011-09-15: Version 1.2: allow flipping the clock",
    "2014-01-16: Version 1.3: added noexcept and enum class",
    "2014-03-28: version 1.4: replaced Rect by Boost.Geometry its box class"
  };
}

void ribi::ruco::ClockWidget::OnResize() noexcept
{
  m_clock->SetGeometry(this->GetGeometry());
}

boost::shared_ptr<ribi::TextCanvas> ribi::ruco::ClockWidget::ToTextCanvas() const noexcept
{
  const int size = 5;
  const boost::shared_ptr<ribi::TextCanvas> c(
    new TextCanvas(size,size)
  );

/*

  01234567890123456789012

0 /-\    ---------    /-\
1 | |----         ----| |
2 \-/                 \-/
3  | /-\    /-\    /-\ |
4  | |4|    |5|    |9| |
5  | \-/    \-/    \-/ |
6  |     /\            |
7 |      ||     /\      |
8 |      \/     \/      |
9 |  /-\    /-\    /-\  |
0 |  |1|    |1|    |3|  |
1 |  \-/    \-/    \-/  |
2 |      /\             |
3 |      ||     /\      |
4  |     \/     \/     |
5  | /-\    /-\    /-\ |
6  | |3|    |3|    |B| |
7  | \-/    \-/    \-/ |
8 /-\                 /-\
9 | |----         ----| |
0 \-/    ---------    \-/

Simpler version:

1 2 3
. |
2 A 4
| .
4 5 6

*/

  const boost::shared_ptr<const Pegs> pegs {
    GetDisplayFront()
    ? GetRubiksClock()->GetFrontPegs()
    : GetRubiksClock()->GetBackPegs()
  };

  for (int peg_row = 0; peg_row!=2; ++peg_row)
  {
    for (int peg_col = 0; peg_col!=2; ++peg_col)
    {
      const char p {pegs->m_pegs[peg_row][peg_col]->GetToggleButton()->IsPressed()
        ? '.' : '|'
      };
      const int x = 1 + (peg_col * 2);
      const int y = 1 + (peg_row * 2);
      c->PutChar(x,y,p);
    }
  }
  const boost::shared_ptr<const Times> times {
    GetDisplayFront()
    ? GetRubiksClock()->GetFrontTimes()
    : GetRubiksClock()->GetBackTimes()
  };

  for (int time_row = 0; time_row!=3; ++time_row)
  {
    for (int time_col = 0; time_col!=3; ++time_col)
    {

      const int time { times->times[time_row][time_col]->GetRubiksClockDial()->GetTime() };
      const char p = time < 10 ? '0' + time : 'A' + (time - 10);
      const int x = time_col * 2;
      const int y = time_row * 2;
      c->PutChar(x,y,p);
    }
  }

  return c;
}

std::ostream& ribi::ruco::operator<<(std::ostream& os, const ribi::ruco::ClockWidget& widget) noexcept
{
  os
    << "<RubiksClockWidget>"
    << *widget.m_clock
    //<< widget.GetGeometry()
    << "</RubiksClockWidget>";
  return os;
}

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml