<tb@panthema.net>
<http://www.gnu.org/licenses/>
#ifndef WSORTVIEW_H
#define WSORTVIEW_H
#include <wx/wx.h>
#include <wx/thread.h>
#include <wx/log.h>
#include <vector>
#include <algorithm>
#define ASSERT(cond) do { if (!(cond)) { \
wxLogError(_("Assertion failed:\n%s in %s:%d"), \
_T(#cond), _T(__FILE__), __LINE__); \
wxLog::FlushActive(); \
abort(); \
} } while(0)
extern bool g_sound_on;
extern double g_sound_sustain;
void SoundCallback(void *udata, unsigned char *stream, int len);
void SoundReset();
void SoundAccess(size_t i);
extern size_t g_compare_count;
extern size_t g_access_count;
class ArrayItem
{
public:
typedef int value_type;
protected:
value_type value;
public:
ArrayItem() {}
explicit ArrayItem(const value_type& d) : value(d) {}
ArrayItem(const ArrayItem& v) : value(v.value) {}
const value_type& get() const
{ OnAccess(*this); return value; }
static void OnAccess(const ArrayItem& a);
const value_type& get_direct() const
{ return value; }
bool operator== (const ArrayItem& v) const
{ OnComparison(*this,v); return (value == v.value); }
bool operator!= (const ArrayItem& v) const
{ OnComparison(*this,v); return (value != v.value); }
bool operator< (const ArrayItem& v) const
{ OnComparison(*this,v); return (value < v.value); }
bool operator<= (const ArrayItem& v) const
{ OnComparison(*this,v); return (value <= v.value); }
bool operator> (const ArrayItem& v) const
{ OnComparison(*this,v); return (value > v.value); }
bool operator>= (const ArrayItem& v) const
{ OnComparison(*this,v); return (value >= v.value); }
int cmp(const ArrayItem& v) const
{ OnComparison(*this,v); return (value == v.value ? 0 : value < v.value ? -1 : +1); }
int compareTo(const ArrayItem& v) const
{ return cmp(v); }
static void OnComparison(const ArrayItem& a, const ArrayItem& b);
};
extern double g_delay;
extern bool g_algo_running;
extern wxString g_algo_name;
class WSortView : public wxPanel
{
public:
WSortView(wxWindow *parent, int id, class WMain_wxg* wmain);
~WSortView();
class WMain* wmain;
void RepaintNow();
virtual void OnPaint(wxPaintEvent& pe);
virtual void OnSize(wxSizeEvent& se);
void paint(wxDC& dc, const wxSize& dcsize);
public:
DECLARE_EVENT_TABLE();
protected:
std::vector<ArrayItem> m_array;
ArrayItem::value_type m_array_max;
size_t m_access1, m_access2;
std::vector<unsigned int> m_access_list;
wxMutex m_mutex;
std::vector<unsigned char> m_mark;
std::vector< std::pair<volatile ssize_t*,unsigned char> > m_watch;
bool m_is_sorted;
bool m_stepwise;
wxSemaphore m_step_semaphore;
public:
void FillData(unsigned int schema, size_t arraysize);
void FillInputlist(wxControlWithItems* list);
bool IsSorted() const { return m_is_sorted; }
void CheckSorted();
void SetStepwise(bool v) { m_stepwise = v; }
void DoStepwise();
protected:
void ResetArray(size_t size);
void FinishFill();
void OnAccess();
void SaveAccess(size_t i);
unsigned char InWatchList(ssize_t idx) const;
public:
size_t size() const { return m_array.size(); }
const ArrayItem::value_type& array_max() const
{ return m_array_max; }
void DoDelay(double delay);
ArrayItem& operator[](size_t i)
{
ASSERT(i < m_array.size());
if (m_access1 != i)
{
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = i;
m_access_list.push_back(i);
}
OnAccess();
}
return m_array[i];
}
ArrayItem& get_nocount(size_t i)
{
ASSERT(i < m_array.size());
if (m_access1 != i)
{
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = i;
m_access_list.push_back(i);
}
--g_access_count;
OnAccess();
}
return m_array[i];
}
void set(size_t i, const ArrayItem& v)
{
ASSERT(i < m_array.size());
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = i;
m_access_list.push_back(i);
m_array[i] = v;
}
OnAccess();
}
void swap(size_t i, size_t j)
{
ASSERT(i < m_array.size());
ASSERT(j < m_array.size());
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = i;
m_access2 = j;
m_access_list.push_back(i);
m_access_list.push_back(j);
}
OnAccess();
std::swap(m_array[i], m_array[j]);
OnAccess();
m_access2 = -1;
}
void mark(size_t i, int color = 1)
{
ASSERT(i < m_array.size());
m_mark[i] = color;
}
void mark_swap(size_t i, size_t j)
{
ASSERT(i < m_array.size());
ASSERT(j < m_array.size());
std::swap(m_mark[i], m_mark[j]);
}
void unmark(size_t i)
{
ASSERT(i < m_array.size());
m_mark[i] = 0;
}
void unmark_all()
{
m_access1 = m_access2 = -1;
std::fill(m_mark.begin(), m_mark.end(), 0);
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access_list.clear();
}
void watch(volatile ssize_t* idxptr, unsigned char color=1)
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_watch.push_back( std::make_pair(idxptr,color) );
}
void unwatch_all()
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_watch.clear();
}
};
class SortAlgoThread : public wxThread
{
protected:
class WMain* m_wmain;
class WSortView& m_array;
size_t m_algo;
public:
SortAlgoThread(class WMain* wmain, class WSortView& array, size_t algo);
virtual ExitCode Entry();
void Exit();
};
#endif