<commit_before>#include "stochastic.h"
#include "accumulator.h"
#include "sampler.h"
#include "file/logger.h"
#include "util/log_search.hpp"
#include "util/random.hpp"
#include "util/thread_pool.h"
#include "util/timer.h"
#include "optimize.h"

namespace ncv
{
        namespace detail
        {
                static opt_state_t tune(
                        trainer_data_t& data,
                        stochastic_optimizer optimizer, scalar_t alpha0, scalar_t decay)
                {
                        const samples_t tsamples = data.m_tsampler.get();
                        const size_t epochs = 1;

                        // construct the optimization problem (NB: one random sample at the time)
                        size_t index = 0;

                        auto fn_size = ncv::make_opsize(data);
                        auto fn_fval = ncv::make_opfval(data, tsamples, index);
                        auto fn_grad = ncv::make_opgrad(data, tsamples, index);

                        auto fn_wlog = nullptr;
                        auto fn_elog = nullptr;
                        auto fn_ulog = nullptr;

                        // assembly optimization problem & optimize the model
                        opt_state_t opt = ncv::minimize(
                                fn_size, fn_fval, fn_grad, fn_wlog, fn_elog, fn_ulog,
                                data.m_x0, optimizer, epochs, tsamples.size(), alpha0, decay);

                        // OK, cumulate the loss value
                        data.m_lacc.reset(opt.x);
                        data.m_lacc.update(data.m_task, tsamples, data.m_loss);

                        opt.f = data.m_lacc.value();
                        return opt;
                }

                static trainer_result_t train(
                        trainer_data_t& data,
                        stochastic_optimizer optimizer, size_t epochs, scalar_t alpha0, scalar_t decay,
                        thread_pool_t::mutex_t& mutex)
                {
                        samples_t tsamples = data.m_tsampler.get();
                        samples_t vsamples = data.m_vsampler.get();

                        trainer_result_t result;

                        const ncv::timer_t timer;

                        // construct the optimization problem (NB: one random sample at the time)
                        size_t index = 0, epoch = 0;

                        auto fn_size = ncv::make_opsize(data);
                        auto fn_fval = ncv::make_opfval(data, tsamples, index);
                        auto fn_grad = ncv::make_opgrad(data, tsamples, index);

                        auto fn_wlog = ncv::make_opwlog();
                        auto fn_elog = ncv::make_opelog();
                        auto fn_ulog = [&] (const opt_state_t& state)
                        {
                                // shuffle randomly the training samples after each epoch
                                random_t<size_t> xrng(0, tsamples.size());
                                random_index_t<size_t> xrnd(xrng);

                                std::random_shuffle(tsamples.begin(), tsamples.end(), xrnd);

                                // evaluate training samples
                                data.m_lacc.reset(state.x);
                                data.m_lacc.update(data.m_task, tsamples, data.m_loss);
                                const scalar_t tvalue = data.m_lacc.value();
                                const scalar_t terror_avg = data.m_lacc.avg_error();
                                const scalar_t terror_var = data.m_lacc.var_error();

                                // evaluate validation samples
                                data.m_lacc.reset(state.x);
                                data.m_lacc.update(data.m_task, vsamples, data.m_loss);
                                const scalar_t vvalue = data.m_lacc.value();
                                const scalar_t verror_avg = data.m_lacc.avg_error();
                                const scalar_t verror_var = data.m_lacc.var_error();

                                epoch ++;

                                // OK, update the optimum solution
                                const thread_pool_t::lock_t lock(mutex);

                                result.update(state.x, tvalue, terror_avg, terror_var, vvalue, verror_avg, verror_var,
                                              epoch, scalars_t({ alpha0, decay, data.m_lacc.lambda() }));

                                log_info()
                                        << "[train = " << tvalue << "/" << terror_avg
                                        << ", valid = " << vvalue << "/" << verror_avg
                                        << ", xnorm = " << state.x.lpNorm<Eigen::Infinity>()
                                        << ", alpha = " << alpha0
                                        << ", decay = " << decay
                                        << ", epoch = " << epoch << "/" << epochs
                                        << ", lambda = " << data.m_lacc.lambda()
                                        << "] done in " << timer.elapsed() << ".";
                        };

                        // assembly optimization problem & optimize the model
                        ncv::minimize(fn_size, fn_fval, fn_grad, fn_wlog, fn_elog, fn_ulog,
                                      data.m_x0, optimizer, epochs, tsamples.size(), alpha0, decay);

                        // OK
                        return result;
                }
        }

        trainer_result_t stochastic_train(
                const model_t& model, const task_t& task, const sampler_t& tsampler, const sampler_t& vsampler, size_t nthreads,
                const loss_t& loss, const string_t& criterion,
                stochastic_optimizer optimizer, size_t epochs)
        {
                thread_pool_t::mutex_t mutex;

                // operator to train for a given regularization factor
                const auto op = [&] (scalar_t lambda)
                {
                        vector_t x0;
                        model.save_params(x0);

                        opt_state_t opt_state;
                        scalar_t opt_alpha = 1.00;
                        scalar_t opt_decay = 0.50;

                        // operator to tune the learning rate
                        const auto op_lrate = [&] (scalar_t alpha)
                        {
                                accumulator_t lacc(model, 1, criterion, criterion_t::type::value, lambda);
                                accumulator_t gacc(model, 1, criterion, criterion_t::type::vgrad, lambda);

                                trainer_data_t data(task, tsampler, vsampler, loss, x0, lacc, gacc);

                                const scalars_t decays = { 0.50, 0.75, 1.00 };

                                // also tune the decay rate
                                std::set<std::pair<opt_state_t, scalar_t> > states;
                                for (scalar_t decay : decays)
                                {
                                        const ncv::timer_t timer;

                                        const opt_state_t state = detail::tune(data, optimizer, alpha, decay);

                                        const thread_pool_t::lock_t lock(mutex);

                                        log_info()
                                                << "[tuning: loss = " << state.f
                                                << ", alpha = " << alpha
                                                << ", decay = " << decay
                                                << ", lambda = " << data.m_lacc.lambda()
                                                << "] done in " << timer.elapsed() << ".";

                                        states.insert(std::make_pair(state, decay));
                                }

                                if (states.begin()->first < opt_state)
                                {
                                        opt_state = states.begin()->first;
                                        opt_alpha = alpha;
                                        opt_decay = states.begin()->second;
                                }

                                return states.begin()->first;
                        };

                        thread_pool_t wpool(nthreads);
                        log_min_search_mt(op_lrate, wpool, -6.0, 0.0, 0.5, nthreads);

                        // train the model using the tuned learning rate & decay rate
                        {
                                accumulator_t lacc(model, 1, criterion, criterion_t::type::value, lambda);
                                accumulator_t gacc(model, 1, criterion, criterion_t::type::vgrad, lambda);

                                trainer_data_t data(task, tsampler, vsampler, loss, x0, lacc, gacc);

                                return detail::train(data, optimizer, epochs, opt_alpha, opt_decay, mutex);
                        }
                };

                // tune the regularization factor (if needed)
                if (accumulator_t::can_regularize(criterion))
                {
                        thread_pool_t wpool(nthreads);
                        return log_min_search_mt(op, wpool, -4.0, +4.0, 0.5, nthreads).first;
                }

                else
                {
                        return op(0.0);
                }
        }
}
<commit_msg>tune learning rate for all epochs (miss-leading results for a single epoch)<commit_after>#include "stochastic.h"
#include "accumulator.h"
#include "sampler.h"
#include "file/logger.h"
#include "util/log_search.hpp"
#include "util/random.hpp"
#include "util/thread_pool.h"
#include "util/timer.h"
#include "optimize.h"

namespace ncv
{
        namespace detail
        {
                static void train(
                        trainer_data_t& data,
                        stochastic_optimizer optimizer, size_t epochs, scalar_t alpha0, scalar_t decay,
                        trainer_result_t& result, thread_pool_t::mutex_t& mutex)
                {
                        samples_t tsamples = data.m_tsampler.get();
                        samples_t vsamples = data.m_vsampler.get();

                        const ncv::timer_t timer;

                        // construct the optimization problem (NB: one random sample at the time)
                        size_t index = 0, epoch = 0;

                        auto fn_size = ncv::make_opsize(data);
                        auto fn_fval = ncv::make_opfval(data, tsamples, index);
                        auto fn_grad = ncv::make_opgrad(data, tsamples, index);

                        auto fn_wlog = ncv::make_opwlog();
                        auto fn_elog = ncv::make_opelog();
                        auto fn_ulog = [&] (const opt_state_t& state)
                        {
                                // shuffle randomly the training samples after each epoch
                                random_t<size_t> xrng(0, tsamples.size());
                                random_index_t<size_t> xrnd(xrng);

                                std::random_shuffle(tsamples.begin(), tsamples.end(), xrnd);

                                // evaluate training samples
                                data.m_lacc.reset(state.x);
                                data.m_lacc.update(data.m_task, tsamples, data.m_loss);
                                const scalar_t tvalue = data.m_lacc.value();
                                const scalar_t terror_avg = data.m_lacc.avg_error();
                                const scalar_t terror_var = data.m_lacc.var_error();

                                // evaluate validation samples
                                data.m_lacc.reset(state.x);
                                data.m_lacc.update(data.m_task, vsamples, data.m_loss);
                                const scalar_t vvalue = data.m_lacc.value();
                                const scalar_t verror_avg = data.m_lacc.avg_error();
                                const scalar_t verror_var = data.m_lacc.var_error();

                                epoch ++;

                                // OK, update the optimum solution
                                const thread_pool_t::lock_t lock(mutex);

                                result.update(state.x, tvalue, terror_avg, terror_var, vvalue, verror_avg, verror_var,
                                              epoch, scalars_t({ alpha0, decay, data.m_lacc.lambda() }));

                                log_info()
                                        << "[train = " << tvalue << "/" << terror_avg
                                        << ", valid = " << vvalue << "/" << verror_avg
                                        << ", xnorm = " << state.x.lpNorm<Eigen::Infinity>()
                                        << ", alpha = " << alpha0
                                        << ", decay = " << decay
                                        << ", epoch = " << epoch << "/" << epochs
                                        << ", lambda = " << data.m_lacc.lambda()
                                        << "] done in " << timer.elapsed() << ".";
                        };

                        // assembly optimization problem & optimize the model
                        ncv::minimize(fn_size, fn_fval, fn_grad, fn_wlog, fn_elog, fn_ulog,
                                      data.m_x0, optimizer, epochs, tsamples.size(), alpha0, decay);
                }
        }

        trainer_result_t stochastic_train(
                const model_t& model, const task_t& task, const sampler_t& tsampler, const sampler_t& vsampler, size_t nthreads,
                const loss_t& loss, const string_t& criterion,
                stochastic_optimizer optimizer, size_t epochs)
        {
                thread_pool_t::mutex_t mutex;

                // operator to train for a given regularization factor
                const auto op = [&] (scalar_t lambda)
                {
                        vector_t x0;
                        model.save_params(x0);

                        // operator to tune the learning rate
                        const auto op_lrate = [&] (scalar_t alpha)
                        {
                                accumulator_t lacc(model, 1, criterion, criterion_t::type::value, lambda);
                                accumulator_t gacc(model, 1, criterion, criterion_t::type::vgrad, lambda);

                                trainer_data_t data(task, tsampler, vsampler, loss, x0, lacc, gacc);

                                // also tune the decay rate (if possible)
                                const scalars_t decays = (optimizer == stochastic_optimizer::NAG) ?
                                        scalars_t({ 1.00 }) : scalars_t({ 0.50, 0.75, 1.00 });

                                trainer_result_t result;

                                for (scalar_t decay : decays)
                                {
                                        detail::train(data, optimizer, epochs, alpha, decay, result, mutex);
                                }

                                return result;
                        };

                        thread_pool_t wpool(nthreads);
                        return log_min_search_mt(op_lrate, wpool, -6.0, 0.0, 0.5, nthreads).first;
                };

                // tune the regularization factor (if needed)
                if (accumulator_t::can_regularize(criterion))
                {
                        thread_pool_t wpool(nthreads);
                        return log_min_search_mt(op, wpool, -4.0, +4.0, 0.5, nthreads).first;
                }

                else
                {
                        return op(0.0);
                }
        }
}
<|endoftext|>


<commit_before>// SimpleGraph.cpp : implementation file
//

#include "stdafx.h"
#include "HexEditView.h"
#include "SimpleGraph.h"
#include "misc.h"

// CSimpleGraph

IMPLEMENT_DYNAMIC(CSimpleGraph, CWnd)

CSimpleGraph::CSimpleGraph()
{
	m_pdc = NULL;
	m_bar = -1;
}

void CSimpleGraph::SetData(FILE_ADDRESS maximum, std::vector<FILE_ADDRESS> val, std::vector<COLORREF> col)
{
	if (val == m_val && col == m_col)
		return;                         // no change

	ASSERT(val.size() == col.size());
	m_max = maximum;
	m_val.swap(val);
	m_col.swap(col);

	update();
}

void CSimpleGraph::update()
{
	CRect rct;
	GetClientRect(rct);

	// If the graph has been resized we need a new DC/bitmap
	if (m_rct != rct)
	{
		m_rct = rct;

		// Delete old DC/bitmap
		if (m_pdc != NULL)
		{
			delete m_pdc;
			m_pdc = NULL;
			m_bm.DeleteObject();
			m_hfnt.DeleteObject();
			m_vfnt.DeleteObject();
		}

		// Recreate DC/bitmap for drawing into
		CDC* pDC = GetDC();
		m_pdc = new CDC();
		m_pdc->CreateCompatibleDC(pDC);
		m_bm.CreateCompatibleBitmap(pDC, rct.Width(), rct.Height());
		m_pdc->SelectObject(&m_bm);

		// Set up text including creating the font
		LOGFONT lf;
		memset(&lf, '\0', sizeof(lf));
		lf.lfHeight = 12;
		strcpy(lf.lfFaceName, "Tahoma");   // Simple font face for small digits
		m_hfnt.CreateFontIndirect(&lf);
		lf.lfEscapement = 900;             // text at 90 degrees
		m_vfnt.CreateFontIndirect(&lf);

		m_pdc->SetBkMode(TRANSPARENT);
		m_pdc->SetTextColor(m_axes);       // use same colour as axes for now
	}

	// Get adjusted colours
	COLORREF *pc = new COLORREF[m_col.size()];
	for (int ii = 0; ii < m_col.size(); ++ii)
		pc[ii] = add_contrast(m_col[ii], m_back);

	// Draw background
	m_pdc->FillSolidRect(0, 0, m_rct.Width(), m_rct.Height(), m_back);
	draw_axes();

	int width = m_rct.Width() - m_left - m_right;     // width of the actual graph area
	int height = m_rct.Height() - m_top - m_bottom;   // height of the graph
	int ypos = m_rct.Height() - m_bottom;             // bottom of the graph (dist. from rect top)

	// Draw bars of graph
	ASSERT(m_val.size() == m_col.size());
	int xpos = m_left;
	for (int ii = 0; ii < m_val.size(); ++ii)
	{
		int next_xpos = m_left + (width*(ii+1))/m_val.size();
		int cy = int((m_val[ii]*height)/m_max);

		m_pdc->FillSolidRect(xpos, ypos - cy, next_xpos - xpos, cy, pc[ii]);        // draw bar for this byte value
		//m_pdc->FillSolidRect(xpos, ypos - cy, next_xpos - xpos,  1, RGB(0, 0, 0));  // add black tip to all bars

		// Add ticks
		if (ii % 16 == 0)
		{
			int siz;
			if (ii %64 == 0)
				siz = 4;
			else
				siz = 2;
			m_pdc->FillSolidRect(xpos - 1, ypos + 1, 1, siz, m_axes);
		}
		xpos = next_xpos;
	}
	m_pdc->FillSolidRect(xpos - 1, ypos + 1, 1, 4, m_axes);   // Right end tick
	delete[] pc;

	Invalidate();
}

void CSimpleGraph::draw_axes()
{
	int width = m_rct.Width() - m_left - m_right;
	int height = m_rct.Height() - m_top - m_bottom;

	m_pdc->FillSolidRect(m_left - 1, m_top - 1, 1, height + 1, m_axes);      // vert axis

	// Calculate tick interval, units etc for the vertical axis
	int max;                         // scaled max value
	CString ustr;                    // scaling unit
	if (m_max >= 2000000000)
	{
		max = int(m_max/1000000000);
		ustr = "Billions";
	}
	else if (m_max >= 2000000)
	{
		max = int(m_max/1000000);
		ustr = "Millions";
	}
	else if (m_max >= 2000)
	{
		max = int(m_max/1000);
		ustr = "Thousands";
	}
	else
	{
		max = int(m_max);
		ustr = "";
	}

	int max_ticks = height/20;              // leave at least 20 pixels between ticks
	int min_spacing = max_ticks == 0 ? max : max/max_ticks + 1;    // min tick distance in graph units

	char buf[10];
	sprintf(buf, "%d", min_spacing);
	double mag = pow(10.0, double(strlen(buf) - 1));   // max magnitude
	double vv = min_spacing/mag;

	int tick;                              // how far apart are ticks in scaled units
	if (vv > 5.0)
		tick = 10 * int(mag);
	else if (vv > 2.0)
		tick = 5 * int(mag);
	else if (vv > 1.0)
		tick = 2 * int(mag);
	else
		tick = int(mag);

	CRect rct;
	m_pdc->SelectObject(&m_hfnt);
	for (int tt = 0; tt < max; tt += tick)
	{
		int ypos = m_rct.Height() - m_bottom - (tt*height)/max;    // xxx is this right as max is rounded??
		m_pdc->FillSolidRect(m_left - 3, ypos, 3, 1, m_axes);

		// Draw units next to tick
		//if (tt < (max*7)/8)        // don't draw near the top so we have room for the "Show" button
		{
			sprintf(buf, "%d", tt);
			rct.left = 0;
			rct.right = 28;
			rct.bottom = ypos + 7;
			rct.top = rct.bottom - 20;
			m_pdc->DrawText(buf, strlen(buf), rct, DT_SINGLELINE | DT_BOTTOM | DT_RIGHT | DT_NOCLIP);
			//m_pdc->ExtTextOut(14, ypos-7, 0, NULL, buf, strlen(buf), NULL);
		}
	}

	// Vertical unit scaling text
	m_pdc->SelectObject(&m_vfnt);
	m_pdc->ExtTextOutA(0, m_rct.Height() - m_bottom, 0, NULL, ustr, strlen(ustr), NULL);

	// Draw horizontal axis
	m_pdc->FillSolidRect(m_left - 1, m_rct.Height() - m_bottom, width + 1, 1, m_axes);
}

void CSimpleGraph::track_mouse(unsigned long flag)
{
	TRACKMOUSEEVENT tme;
	tme.cbSize = sizeof(tme);
	tme.dwFlags = flag;
	tme.dwHoverTime = 0;
	tme.hwndTrack = m_hWnd;

	VERIFY(::_TrackMouseEvent(&tme));
}

int CSimpleGraph::get_bar(CPoint pt)
{
	++pt.x;  // mouse posn seems to be out by 1 pixel
	if (pt.y <= m_top || pt.y >= m_rct.Height() - m_bottom ||
		pt.x < m_left || pt.x > m_rct.Width() - m_right)
	{
		// Outside graph area so return
		return -1;
	}

	int retval = ((pt.x - m_left)*m_val.size())/(m_rct.Width() - m_left - m_right);
	if (retval >= m_val.size())
		retval = m_val.size() - 1;

	return retval;
}

BEGIN_MESSAGE_MAP(CSimpleGraph, CWnd)
	ON_WM_PAINT()
	ON_WM_SIZE()
	ON_WM_SETCURSOR()
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
END_MESSAGE_MAP()

// CSimpleGraph message handlers
void CSimpleGraph::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	CRect rct;
	GetClientRect(rct);

	// Just BLT the current graph into the display
	dc.BitBlt(rct.left, rct.top, rct.Width(), rct.Height(), m_pdc, 0, 0, SRCCOPY);
}

void CSimpleGraph::OnSize(UINT nType, int cx, int cy)
{
	__super::OnSize(nType, cx, cy);
	update();
}

BOOL CSimpleGraph::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	CPoint pt;
	::GetCursorPos(&pt);            // get mouse location (screen coords)
	ScreenToClient(&pt);
	if (get_bar(pt) > -1)
		::SetCursor(theApp.LoadCursor(IDC_INFO));  // show info cursor if over the graph
	else
		::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
	return TRUE;
}

void CSimpleGraph::OnMouseMove(UINT nFlags, CPoint point)
{
	CWnd::OnMouseMove(nFlags, point);

	// Check for hover if no tip window is visible
	if (!m_tip.IsWindowVisible())
		track_mouse(TME_HOVER);
	else if (get_bar(point) != m_bar && !m_tip.FadingOut())
		m_tip.Hide(300);
}

LRESULT CSimpleGraph::OnMouseHover(WPARAM, LPARAM lp)
{
	CPoint pt(LOWORD(lp), HIWORD(lp));  // client window coords

	CHexEditView *pv = GetView();
	ASSERT(pv != NULL);

	m_bar = get_bar(pt);
	if (m_bar > -1 && !m_tip.IsWindowVisible())
	{
		// Update the tip info
		m_tip.Clear();
		CString ss;
		if (theApp.hex_ucase_)
			ss.Format("Byte: %d [%02.2Xh] %s", m_bar, m_bar, pv->DescChar(m_bar));
		else
			ss.Format("Byte: %d [%02.2xh] %s", m_bar, m_bar, pv->DescChar(m_bar));
		m_tip.AddString(ss);

		char buf[32];                   // used with sprintf (CString::Format can't handle __int64)
		sprintf(buf, "%I64d", m_val[m_bar]);
		ss = buf;
		AddCommas(ss);
		m_tip.AddString("Count: " +ss);

		// Work out the tip window display position and move the tip window there
		CPoint tip_pt = pt + CSize(16, 16);
		ClientToScreen(&tip_pt);
		m_tip.Move(tip_pt, false);

		m_tip.Show();
		track_mouse(TME_LEAVE);
		return 0;  // return 0 to say we processed it
	}

	return 1;
}

LRESULT CSimpleGraph::OnMouseLeave(WPARAM, LPARAM lp)
{
	// Make sure we hide the tip window when the mouse leave the window (no more move messages are received)
	m_tip.Hide(300);
	return 0;
}
<commit_msg>Avoid divide by zero in Count property page when the file is empty<commit_after>// SimpleGraph.cpp : implementation file
//

#include "stdafx.h"
#include "HexEditView.h"
#include "SimpleGraph.h"
#include "misc.h"

// CSimpleGraph

IMPLEMENT_DYNAMIC(CSimpleGraph, CWnd)

CSimpleGraph::CSimpleGraph()
{
	m_pdc = NULL;
	m_bar = -1;
}

void CSimpleGraph::SetData(FILE_ADDRESS maximum, std::vector<FILE_ADDRESS> val, std::vector<COLORREF> col)
{
	if (val == m_val && col == m_col)
		return;                         // no change

	ASSERT(val.size() == col.size());
	m_max = maximum;
	if (m_max < 1) m_max = 1;  // avoid divide by zero
	m_val.swap(val);
	m_col.swap(col);

	update();
}

void CSimpleGraph::update()
{
	CRect rct;
	GetClientRect(rct);

	// If the graph has been resized we need a new DC/bitmap
	if (m_rct != rct)
	{
		m_rct = rct;

		// Delete old DC/bitmap
		if (m_pdc != NULL)
		{
			delete m_pdc;
			m_pdc = NULL;
			m_bm.DeleteObject();
			m_hfnt.DeleteObject();
			m_vfnt.DeleteObject();
		}

		// Recreate DC/bitmap for drawing into
		CDC* pDC = GetDC();
		m_pdc = new CDC();
		m_pdc->CreateCompatibleDC(pDC);
		m_bm.CreateCompatibleBitmap(pDC, rct.Width(), rct.Height());
		m_pdc->SelectObject(&m_bm);

		// Set up text including creating the font
		LOGFONT lf;
		memset(&lf, '\0', sizeof(lf));
		lf.lfHeight = 12;
		strcpy(lf.lfFaceName, "Tahoma");   // Simple font face for small digits
		m_hfnt.CreateFontIndirect(&lf);
		lf.lfEscapement = 900;             // text at 90 degrees
		m_vfnt.CreateFontIndirect(&lf);

		m_pdc->SetBkMode(TRANSPARENT);
		m_pdc->SetTextColor(m_axes);       // use same colour as axes for now
	}

	// Get adjusted colours
	COLORREF *pc = new COLORREF[m_col.size()];
	for (int ii = 0; ii < m_col.size(); ++ii)
		pc[ii] = add_contrast(m_col[ii], m_back);

	// Draw background
	m_pdc->FillSolidRect(0, 0, m_rct.Width(), m_rct.Height(), m_back);
	draw_axes();

	int width = m_rct.Width() - m_left - m_right;     // width of the actual graph area
	int height = m_rct.Height() - m_top - m_bottom;   // height of the graph
	int ypos = m_rct.Height() - m_bottom;             // bottom of the graph (dist. from rect top)

	// Draw bars of graph
	ASSERT(m_val.size() == m_col.size());
	int xpos = m_left;
	for (int ii = 0; ii < m_val.size(); ++ii)
	{
		int next_xpos = m_left + (width*(ii+1))/m_val.size();
		int cy = int((m_val[ii]*height)/m_max);

		m_pdc->FillSolidRect(xpos, ypos - cy, next_xpos - xpos, cy, pc[ii]);        // draw bar for this byte value
		//m_pdc->FillSolidRect(xpos, ypos - cy, next_xpos - xpos,  1, RGB(0, 0, 0));  // add black tip to all bars

		// Add ticks
		if (ii % 16 == 0)
		{
			int siz;
			if (ii %64 == 0)
				siz = 4;
			else
				siz = 2;
			m_pdc->FillSolidRect(xpos - 1, ypos + 1, 1, siz, m_axes);
		}
		xpos = next_xpos;
	}
	m_pdc->FillSolidRect(xpos - 1, ypos + 1, 1, 4, m_axes);   // Right end tick
	delete[] pc;

	Invalidate();
}

void CSimpleGraph::draw_axes()
{
	int width = m_rct.Width() - m_left - m_right;
	int height = m_rct.Height() - m_top - m_bottom;

	m_pdc->FillSolidRect(m_left - 1, m_top - 1, 1, height + 1, m_axes);      // vert axis

	// Calculate tick interval, units etc for the vertical axis
	int max;                         // scaled max value
	CString ustr;                    // scaling unit
	if (m_max >= 2000000000)
	{
		max = int(m_max/1000000000);
		ustr = "Billions";
	}
	else if (m_max >= 2000000)
	{
		max = int(m_max/1000000);
		ustr = "Millions";
	}
	else if (m_max >= 2000)
	{
		max = int(m_max/1000);
		ustr = "Thousands";
	}
	else
	{
		max = int(m_max);
		ustr = "";
	}

	int max_ticks = height/20;              // leave at least 20 pixels between ticks
	int min_spacing = max_ticks == 0 ? max : max/max_ticks + 1;    // min tick distance in graph units

	char buf[10];
	sprintf(buf, "%d", min_spacing);
	double mag = pow(10.0, double(strlen(buf) - 1));   // max magnitude
	double vv = min_spacing/mag;

	int tick;                              // how far apart are ticks in scaled units
	if (vv > 5.0)
		tick = 10 * int(mag);
	else if (vv > 2.0)
		tick = 5 * int(mag);
	else if (vv > 1.0)
		tick = 2 * int(mag);
	else
		tick = int(mag);

	CRect rct;
	m_pdc->SelectObject(&m_hfnt);
	for (int tt = 0; tt < max; tt += tick)
	{
		int ypos = m_rct.Height() - m_bottom - (tt*height)/max;    // xxx is this right as max is rounded??
		m_pdc->FillSolidRect(m_left - 3, ypos, 3, 1, m_axes);

		// Draw units next to tick
		//if (tt < (max*7)/8)        // don't draw near the top so we have room for the "Show" button
		{
			sprintf(buf, "%d", tt);
			rct.left = 0;
			rct.right = 28;
			rct.bottom = ypos + 7;
			rct.top = rct.bottom - 20;
			m_pdc->DrawText(buf, strlen(buf), rct, DT_SINGLELINE | DT_BOTTOM | DT_RIGHT | DT_NOCLIP);
			//m_pdc->ExtTextOut(14, ypos-7, 0, NULL, buf, strlen(buf), NULL);
		}
	}

	// Vertical unit scaling text
	m_pdc->SelectObject(&m_vfnt);
	m_pdc->ExtTextOutA(0, m_rct.Height() - m_bottom, 0, NULL, ustr, strlen(ustr), NULL);

	// Draw horizontal axis
	m_pdc->FillSolidRect(m_left - 1, m_rct.Height() - m_bottom, width + 1, 1, m_axes);
}

void CSimpleGraph::track_mouse(unsigned long flag)
{
	TRACKMOUSEEVENT tme;
	tme.cbSize = sizeof(tme);
	tme.dwFlags = flag;
	tme.dwHoverTime = 0;
	tme.hwndTrack = m_hWnd;

	VERIFY(::_TrackMouseEvent(&tme));
}

int CSimpleGraph::get_bar(CPoint pt)
{
	++pt.x;  // mouse posn seems to be out by 1 pixel
	if (pt.y <= m_top || pt.y >= m_rct.Height() - m_bottom ||
		pt.x < m_left || pt.x > m_rct.Width() - m_right)
	{
		// Outside graph area so return
		return -1;
	}

	int retval = ((pt.x - m_left)*m_val.size())/(m_rct.Width() - m_left - m_right);
	if (retval >= m_val.size())
		retval = m_val.size() - 1;

	return retval;
}

BEGIN_MESSAGE_MAP(CSimpleGraph, CWnd)
	ON_WM_PAINT()
	ON_WM_SIZE()
	ON_WM_SETCURSOR()
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
END_MESSAGE_MAP()

// CSimpleGraph message handlers
void CSimpleGraph::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	CRect rct;
	GetClientRect(rct);

	// Just BLT the current graph into the display
	dc.BitBlt(rct.left, rct.top, rct.Width(), rct.Height(), m_pdc, 0, 0, SRCCOPY);
}

void CSimpleGraph::OnSize(UINT nType, int cx, int cy)
{
	__super::OnSize(nType, cx, cy);
	update();
}

BOOL CSimpleGraph::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	CPoint pt;
	::GetCursorPos(&pt);            // get mouse location (screen coords)
	ScreenToClient(&pt);
	if (get_bar(pt) > -1)
		::SetCursor(theApp.LoadCursor(IDC_INFO));  // show info cursor if over the graph
	else
		::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
	return TRUE;
}

void CSimpleGraph::OnMouseMove(UINT nFlags, CPoint point)
{
	CWnd::OnMouseMove(nFlags, point);

	// Check for hover if no tip window is visible
	if (!m_tip.IsWindowVisible())
		track_mouse(TME_HOVER);
	else if (get_bar(point) != m_bar && !m_tip.FadingOut())
		m_tip.Hide(300);
}

LRESULT CSimpleGraph::OnMouseHover(WPARAM, LPARAM lp)
{
	CPoint pt(LOWORD(lp), HIWORD(lp));  // client window coords

	CHexEditView *pv = GetView();
	ASSERT(pv != NULL);

	m_bar = get_bar(pt);
	if (m_bar > -1 && !m_tip.IsWindowVisible())
	{
		// Update the tip info
		m_tip.Clear();
		CString ss;
		if (theApp.hex_ucase_)
			ss.Format("Byte: %d [%02.2Xh] %s", m_bar, m_bar, pv->DescChar(m_bar));
		else
			ss.Format("Byte: %d [%02.2xh] %s", m_bar, m_bar, pv->DescChar(m_bar));
		m_tip.AddString(ss);

		char buf[32];                   // used with sprintf (CString::Format can't handle __int64)
		sprintf(buf, "%I64d", m_val[m_bar]);
		ss = buf;
		AddCommas(ss);
		m_tip.AddString("Count: " +ss);

		// Work out the tip window display position and move the tip window there
		CPoint tip_pt = pt + CSize(16, 16);
		ClientToScreen(&tip_pt);
		m_tip.Move(tip_pt, false);

		m_tip.Show();
		track_mouse(TME_LEAVE);
		return 0;  // return 0 to say we processed it
	}

	return 1;
}

LRESULT CSimpleGraph::OnMouseLeave(WPARAM, LPARAM lp)
{
	// Make sure we hide the tip window when the mouse leave the window (no more move messages are received)
	m_tip.Hide(300);
	return 0;
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <atomic>
#include <chrono>
#include <future>  // for async()
#include <iostream>
#include <memory>
#include <random>
#include <string>

#include "helper.h"
#include "route_guide.grpc_cb.pb.h"

using grpc_cb::Channel;
using grpc_cb::ChannelSptr;
using grpc_cb::Status;
using routeguide::Point;
using routeguide::Feature;
using routeguide::Rectangle;
using routeguide::RouteSummary;
using routeguide::RouteNote;
using routeguide::RouteGuide::Stub;

const float kCoordFactor = 10000000.0;
static unsigned seed = (unsigned)std::chrono::system_clock::now().time_since_epoch().count();
static std::default_random_engine generator(seed);

Point MakePoint(long latitude, long longitude) {
  Point p;
  p.set_latitude(latitude);
  p.set_longitude(longitude);
  return p;
}

routeguide::Rectangle MakeRect(const Point& lo, const Point& hi) {
  routeguide::Rectangle rect;
  *rect.mutable_lo() = lo;
  *rect.mutable_hi() = hi;
  return rect;
}

routeguide::Rectangle MakeRect(long lo_latitude, long lo_longitude,
                   long hi_latitude, long hi_longitude) {
  return MakeRect(MakePoint(lo_latitude, lo_longitude),
                  MakePoint(hi_latitude, hi_longitude));
}

Feature MakeFeature(const std::string& name,
                    long latitude, long longitude) {
  Feature f;
  f.set_name(name);
  f.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return f;
}

RouteNote MakeRouteNote(const std::string& message,
                        long latitude, long longitude) {
  RouteNote n;
  n.set_message(message);
  n.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return n;
}

void PrintFeature(const Feature& feature) {
  if (!feature.has_location()) {
    std::cout << "Server returns incomplete feature." << std::endl;
    return;
  }
  if (feature.name().empty()) {
    std::cout << "Found no feature at "
        << feature.location().latitude()/kCoordFactor << ", "
        << feature.location().longitude()/kCoordFactor << std::endl;
  }
  else {
    std::cout << "Found feature called " << feature.name()  << " at "
        << feature.location().latitude()/kCoordFactor << ", "
        << feature.location().longitude()/kCoordFactor << std::endl;
  }
}  // PrintFeature()

void PrintServerNote(const RouteNote& server_note) {
  std::cout << "Got message " << server_note.message()
            << " at " << server_note.location().latitude() << ", "
            << server_note.location().longitude() << std::endl;
}

void RandomSleep() {
  std::uniform_int_distribution<int> delay_distribution(500, 1500);
  std::this_thread::sleep_for(std::chrono::milliseconds(
      delay_distribution(generator)));
}

void RunWriteRouteNote(Stub::RouteChat_SyncReaderWriter sync_reader_writer) {
  std::vector<RouteNote> notes{
    MakeRouteNote("First message", 0, 0),
    MakeRouteNote("Second message", 0, 1),
    MakeRouteNote("Third message", 1, 0),
    MakeRouteNote("Fourth message", 0, 0)};
  for (const RouteNote& note : notes) {
    std::cout << "Sending message " << note.message()
              << " at " << note.location().latitude() << ", "
              << note.location().longitude() << std::endl;
    sync_reader_writer.Write(note);
    // RandomSleep();
  }
  sync_reader_writer.CloseWriting();
}

class RouteGuideClient {
 public:
  RouteGuideClient(std::shared_ptr<Channel> channel, const std::string& db)
      : stub_(new Stub(channel)) {
    routeguide::ParseDb(db, &feature_list_);
    assert(!feature_list_.empty());
  }

  void SyncGetFeature() {
    Point point;
    Feature feature;
    point = MakePoint(409146138, -746188906);
    SyncGetOneFeature(point, &feature);
    point = MakePoint(0, 0);
    SyncGetOneFeature(point, &feature);
  }

  void SyncListFeatures() {
    routeguide::Rectangle rect = MakeRect(
        400000000, -750000000, 420000000, -730000000);
    Feature feature;

    std::cout << "Looking for features between 40, -75 and 42, -73"
        << std::endl;

    auto sync_reader(stub_->Sync_ListFeatures(rect));
    while (sync_reader.ReadOne(&feature)) {
      std::cout << "Found feature called "
                << feature.name() << " at "
                << feature.location().latitude()/kCoordFactor << ", "
                << feature.location().longitude()/kCoordFactor << std::endl;
    }
    Status status = sync_reader.RecvStatus();
    if (status.ok()) {
      std::cout << "ListFeatures rpc succeeded." << std::endl;
    } else {
      std::cout << "ListFeatures rpc failed." << std::endl;
    }
  }

  void SyncRecordRoute() {
    Point point;
    const int kPoints = 10;
    std::uniform_int_distribution<int> feature_distribution(
        0, feature_list_.size() - 1);

    auto sync_writer(stub_->Sync_RecordRoute());
    for (int i = 0; i < kPoints; i++) {
      const Feature& f = feature_list_[feature_distribution(generator)];
      std::cout << "Visiting point "
                << f.location().latitude()/kCoordFactor << ", "
                << f.location().longitude()/kCoordFactor << std::endl;
      if (!sync_writer.Write(f.location())) {
        // Broken stream.
        break;
      }
      RandomSleep();
    }
    RouteSummary stats;
    // Recv reponse and status.
    Status status = sync_writer.Close(&stats);  // Todo: timeout
    if (status.ok()) {
      std::cout << "Finished trip with " << stats.point_count() << " points\n"
                << "Passed " << stats.feature_count() << " features\n"
                << "Traveled " << stats.distance() << " meters\n"
                << "It took " << stats.elapsed_time() << " seconds"
                << std::endl;
    } else {
      std::cout << "RecordRoute rpc failed." << std::endl;
    }
  }

  // Todo: Callback on client stream response and status.

  void SyncRouteChat() {
    auto sync_reader_writer(stub_->Sync_RouteChat());
    auto f = std::async(std::launch::async, [sync_reader_writer]() {
        RunWriteRouteNote(sync_reader_writer);
    });

    RouteNote server_note;
    while (sync_reader_writer.ReadOne(&server_note))
        PrintServerNote(server_note);

    f.wait();
    // Todo: Close() should auto close writing.
    Status status = sync_reader_writer.RecvStatus();
    if (!status.ok()) {
      std::cout << "RouteChat rpc failed." << std::endl;
    }
  }

 private:
  bool SyncGetOneFeature(const Point& point, Feature* feature) {
    Status status = stub_->Sync_GetFeature(point, feature);
    if (!status.ok()) {
      std::cout << "GetFeature rpc failed." << std::endl;
      return false;
    }
    PrintFeature(*feature);
    return feature->has_location();
  }

  std::unique_ptr<Stub> stub_;
  std::vector<Feature> feature_list_;
};

void GetFeatureAsync(const ChannelSptr& channel) {
  Stub stub(channel);

  // Ignore error status.
  stub.Async_GetFeature(MakePoint(0, 0),
                       [](const Feature& feature) { PrintFeature(feature); });

  // Ignore response.
  stub.Async_GetFeature(MakePoint(0, 0));

  Point point1 = MakePoint(409146138, -746188906);
  stub.Async_GetFeature(point1,
      [&stub](const Feature& feature) {
        PrintFeature(feature);
        stub.Shutdown();
      },
      [&stub](const Status& err) {
        std::cout << "AsyncGetFeature rpc failed. "
            << err.GetDetails() << std::endl;
        stub.Shutdown();
      });  // AsyncGetFeature()
  stub.Run();  // until stub.Shutdown()
}

void ListFeaturesAsync(const ChannelSptr& channel) {
  Stub stub(channel);
  routeguide::Rectangle rect = MakeRect(
      400000000, -750000000, 420000000, -730000000);
  std::cout << "Looking for features between 40, -75 and 42, -73" << std::endl;

  stub.Async_ListFeatures(rect,
    [](const Feature& feature) {
      std::cout << "Got feature " << feature.name() << " at "
          << feature.location().latitude()/kCoordFactor << ", "
          << feature.location().longitude()/kCoordFactor << std::endl;
    },
    [&stub](const Status& status) {
      std::cout << "End status: (" << status.GetCode() << ") "
          << status.GetDetails() << std::endl;
      stub.Shutdown();  // To break Run().
    });
  stub.Run();  // until stub.Shutdown()
}

void RecordRouteAsync(const ChannelSptr& channel,
                      const std::string& db) {
  assert(!db.empty());
  std::vector<Feature> feature_list;
  routeguide::ParseDb(db, &feature_list);
  assert(!feature_list.empty());

  Point point;
  const int kPoints = 10;
  std::uniform_int_distribution<int> feature_distribution(
      0, feature_list.size() - 1);

  Stub stub(channel);
  auto f = std::async(std::launch::async, [&stub]() { stub.Run(); });

  // ClientAsyncWriter<Point, RouteSummary> async_writer;
  auto async_writer = stub.Async_RecordRoute();
  for (int i = 0; i < kPoints; i++) {
    const Feature& f = feature_list[feature_distribution(generator)];
    std::cout << "Visiting point "
              << f.location().latitude()/kCoordFactor << ", "
              << f.location().longitude()/kCoordFactor << std::endl;
    if (!async_writer.Write(f.location())) {
      // Broken stream.
      break;
    }
    RandomSleep();
  }
  // Recv reponse and status.
  async_writer.Close([](const Status& status, const RouteSummary& resp) {
    if (!status.ok()) {
      std::cout << "RecordRoute rpc failed." << std::endl;
      return;
    }
    std::cout << "Finished trip with " << resp.point_count() << " points\n"
              << "Passed " << resp.feature_count() << " features\n"
              << "Traveled " << resp.distance() << " meters\n"
              << "It took " << resp.elapsed_time() << " seconds" << std::endl;
  });

  // Todo: timeout

  stub.Shutdown();
}  // RecordRouteAsync()

void AsyncWriteRouteNotes(Stub::RouteChat_AsyncReaderWriter async_reader_writer) {
  std::vector<RouteNote> notes{
    MakeRouteNote("First message", 0, 0),
    MakeRouteNote("Second message", 0, 1),
    MakeRouteNote("Third message", 1, 0),
    MakeRouteNote("Fourth message", 0, 0)};
  for (const RouteNote& note : notes) {
    std::cout << "Sending message " << note.message()
              << " at " << note.location().latitude() << ", "
              << note.location().longitude() << std::endl;
    async_reader_writer.Write(note);
    RandomSleep();
  }
  async_reader_writer.CloseWriting();  // Optional.
}

void RouteChatAsync(const ChannelSptr& channel) {
  Stub stub(channel);
  auto f_run = std::async(std::launch::async, [&stub]() {
    stub.Run();
  });

  std::atomic_bool bReaderDone = false;
  auto async_reader_writer(
      stub.Async_RouteChat([&bReaderDone](const Status& status) {
        if (!status.ok()) {
          std::cout << "RouteChat rpc failed. " << status.GetDetails()
                    << std::endl;
        }
        bReaderDone = true;
      }));

  async_reader_writer.ReadEach(
      [](const RouteNote& note) { PrintServerNote(note); });
  AsyncWriteRouteNotes(async_reader_writer);

  while (!bReaderDone)
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  stub.Shutdown();  // To break Run().
}  // RouteChatAsync()

void TestRpcTimeout(const ChannelSptr& channel) {
  Stub stub(channel);
  stub.SetCallTimeoutMs(INT64_MIN);
  Point point = MakePoint(0, 0);
  Feature feature;
  Status status = stub.Sync_GetFeature(point, &feature);
  assert(status.GetCode() == GRPC_STATUS_DEADLINE_EXCEEDED);
}

int main(int argc, char** argv) {
  // Expect only arg: --db_path=path/to/route_guide_db.json.
  std::string db = routeguide::GetDbFileContent(argc, argv);
  assert(!db.empty());
  ChannelSptr channel(new Channel("localhost:50051"));
  RouteGuideClient guide(channel, db);

  TestRpcTimeout(channel);

  std::cout << "---- SyncGetFeature --------------" << std::endl;
  guide.SyncGetFeature();
  std::cout << "---- SyncListFeatures --------------" << std::endl;
  guide.SyncListFeatures();
  std::cout << "---- SyncRecordRoute --------------" << std::endl;
  guide.SyncRecordRoute();
  std::cout << "---- SyncRouteChat --------------" << std::endl;
  guide.SyncRouteChat();

  std::cout << "---- GetFeatureAsync ----" << std::endl;
  GetFeatureAsync(channel);
  std::cout << "---- ListFeaturesAsync ----" << std::endl;
  ListFeaturesAsync(channel);
  std::cout << "---- RecordRouteAsnyc ----" << std::endl;
  RecordRouteAsync(channel, db);
  std::cout << "---- RouteChatAsync ---" << std::endl;
  RouteChatAsync(channel);

  return 0;
}
<commit_msg>Update example output.<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <atomic>
#include <chrono>
#include <future>  // for async()
#include <iostream>
#include <memory>
#include <random>
#include <string>

#include "helper.h"
#include "route_guide.grpc_cb.pb.h"

using grpc_cb::Channel;
using grpc_cb::ChannelSptr;
using grpc_cb::Status;
using routeguide::Point;
using routeguide::Feature;
using routeguide::Rectangle;
using routeguide::RouteSummary;
using routeguide::RouteNote;
using routeguide::RouteGuide::Stub;

const float kCoordFactor = 10000000.0;
static unsigned seed = (unsigned)std::chrono::system_clock::now().time_since_epoch().count();
static std::default_random_engine generator(seed);

Point MakePoint(long latitude, long longitude) {
  Point p;
  p.set_latitude(latitude);
  p.set_longitude(longitude);
  return p;
}

routeguide::Rectangle MakeRect(const Point& lo, const Point& hi) {
  routeguide::Rectangle rect;
  *rect.mutable_lo() = lo;
  *rect.mutable_hi() = hi;
  return rect;
}

routeguide::Rectangle MakeRect(long lo_latitude, long lo_longitude,
                   long hi_latitude, long hi_longitude) {
  return MakeRect(MakePoint(lo_latitude, lo_longitude),
                  MakePoint(hi_latitude, hi_longitude));
}

Feature MakeFeature(const std::string& name,
                    long latitude, long longitude) {
  Feature f;
  f.set_name(name);
  f.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return f;
}

RouteNote MakeRouteNote(const std::string& message,
                        long latitude, long longitude) {
  RouteNote n;
  n.set_message(message);
  n.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return n;
}

void PrintFeature(const Feature& feature) {
  if (!feature.has_location()) {
    std::cout << "Server returns incomplete feature." << std::endl;
    return;
  }
  if (feature.name().empty()) {
    std::cout << "Found no feature at "
        << feature.location().latitude()/kCoordFactor << ", "
        << feature.location().longitude()/kCoordFactor << std::endl;
  }
  else {
    std::cout << "Found feature called " << feature.name()  << " at "
        << feature.location().latitude()/kCoordFactor << ", "
        << feature.location().longitude()/kCoordFactor << std::endl;
  }
}  // PrintFeature()

void PrintServerNote(const RouteNote& server_note) {
  std::cout << "Got message " << server_note.message()
            << " at " << server_note.location().latitude() << ", "
            << server_note.location().longitude() << std::endl;
}

void RandomSleep() {
  std::uniform_int_distribution<int> delay_distribution(500, 1500);
  std::this_thread::sleep_for(std::chrono::milliseconds(
      delay_distribution(generator)));
}

void RunWriteRouteNote(Stub::RouteChat_SyncReaderWriter sync_reader_writer) {
  std::vector<RouteNote> notes{
    MakeRouteNote("First message", 0, 0),
    MakeRouteNote("Second message", 0, 1),
    MakeRouteNote("Third message", 1, 0),
    MakeRouteNote("Fourth message", 0, 0)};
  for (const RouteNote& note : notes) {
    std::cout << "Sending message " << note.message()
              << " at " << note.location().latitude() << ", "
              << note.location().longitude() << std::endl;
    sync_reader_writer.Write(note);
    // RandomSleep();
  }
  sync_reader_writer.CloseWriting();
}

class RouteGuideClient {
 public:
  RouteGuideClient(std::shared_ptr<Channel> channel, const std::string& db)
      : stub_(new Stub(channel)) {
    routeguide::ParseDb(db, &feature_list_);
    assert(!feature_list_.empty());
  }

  void SyncGetFeature() {
    Point point;
    Feature feature;
    point = MakePoint(409146138, -746188906);
    SyncGetOneFeature(point, &feature);
    point = MakePoint(0, 0);
    SyncGetOneFeature(point, &feature);
  }

  void SyncListFeatures() {
    routeguide::Rectangle rect = MakeRect(
        400000000, -750000000, 420000000, -730000000);
    Feature feature;

    std::cout << "Looking for features between 40, -75 and 42, -73"
        << std::endl;

    auto sync_reader(stub_->Sync_ListFeatures(rect));
    while (sync_reader.ReadOne(&feature)) {
      std::cout << "Found feature called "
                << feature.name() << " at "
                << feature.location().latitude()/kCoordFactor << ", "
                << feature.location().longitude()/kCoordFactor << std::endl;
    }
    Status status = sync_reader.RecvStatus();
    if (status.ok()) {
      std::cout << "ListFeatures rpc succeeded." << std::endl;
    } else {
      std::cout << "ListFeatures rpc failed." << std::endl;
    }
  }

  void SyncRecordRoute() {
    Point point;
    const int kPoints = 10;
    std::uniform_int_distribution<int> feature_distribution(
        0, feature_list_.size() - 1);

    auto sync_writer(stub_->Sync_RecordRoute());
    for (int i = 0; i < kPoints; i++) {
      const Feature& f = feature_list_[feature_distribution(generator)];
      std::cout << "Visiting point "
                << f.location().latitude()/kCoordFactor << ", "
                << f.location().longitude()/kCoordFactor << std::endl;
      if (!sync_writer.Write(f.location())) {
        // Broken stream.
        break;
      }
      RandomSleep();
    }
    RouteSummary stats;
    // Recv reponse and status.
    Status status = sync_writer.Close(&stats);  // Todo: timeout
    if (status.ok()) {
      std::cout << "Finished trip with " << stats.point_count() << " points\n"
                << "Passed " << stats.feature_count() << " features\n"
                << "Traveled " << stats.distance() << " meters\n"
                << "It took " << stats.elapsed_time() << " seconds"
                << std::endl;
    } else {
      std::cout << "RecordRoute rpc failed." << std::endl;
    }
  }

  // Todo: Callback on client stream response and status.

  void SyncRouteChat() {
    auto sync_reader_writer(stub_->Sync_RouteChat());
    auto f = std::async(std::launch::async, [sync_reader_writer]() {
        RunWriteRouteNote(sync_reader_writer);
    });

    RouteNote server_note;
    while (sync_reader_writer.ReadOne(&server_note))
        PrintServerNote(server_note);

    f.wait();
    // Todo: Close() should auto close writing.
    Status status = sync_reader_writer.RecvStatus();
    if (!status.ok()) {
      std::cout << "RouteChat rpc failed." << std::endl;
    }
  }

 private:
  bool SyncGetOneFeature(const Point& point, Feature* feature) {
    Status status = stub_->Sync_GetFeature(point, feature);
    if (!status.ok()) {
      std::cout << "GetFeature rpc failed." << std::endl;
      return false;
    }
    PrintFeature(*feature);
    return feature->has_location();
  }

  std::unique_ptr<Stub> stub_;
  std::vector<Feature> feature_list_;
};

void GetFeatureAsync(const ChannelSptr& channel) {
  Stub stub(channel);

  // Ignore error status.
  stub.Async_GetFeature(MakePoint(0, 0),
                       [](const Feature& feature) { PrintFeature(feature); });

  // Ignore response.
  stub.Async_GetFeature(MakePoint(0, 0));

  Point point1 = MakePoint(409146138, -746188906);
  stub.Async_GetFeature(point1,
      [&stub](const Feature& feature) {
        PrintFeature(feature);
        stub.Shutdown();
      },
      [&stub](const Status& err) {
        std::cout << "AsyncGetFeature rpc failed. "
            << err.GetDetails() << std::endl;
        stub.Shutdown();
      });  // AsyncGetFeature()
  stub.Run();  // until stub.Shutdown()
}

void ListFeaturesAsync(const ChannelSptr& channel) {
  Stub stub(channel);
  routeguide::Rectangle rect = MakeRect(
      400000000, -750000000, 420000000, -730000000);
  std::cout << "Looking for features between 40, -75 and 42, -73" << std::endl;

  stub.Async_ListFeatures(rect,
    [](const Feature& feature) {
      std::cout << "Found feature called " << feature.name() << " at "
          << feature.location().latitude()/kCoordFactor << ", "
          << feature.location().longitude()/kCoordFactor << std::endl;
    },
    [&stub](const Status& status) {
      if (status.ok()) {
        std::cout << "ListFeatures rpc succeeded." << std::endl;
      } else {
        std::cout << "ListFeatures rpc failed." << std::endl;
      }
      stub.Shutdown();  // To break Run().
    });
  stub.Run();  // until stub.Shutdown()
}

void RecordRouteAsync(const ChannelSptr& channel,
                      const std::string& db) {
  assert(!db.empty());
  std::vector<Feature> feature_list;
  routeguide::ParseDb(db, &feature_list);
  assert(!feature_list.empty());

  Point point;
  const int kPoints = 10;
  std::uniform_int_distribution<int> feature_distribution(
      0, feature_list.size() - 1);

  Stub stub(channel);
  auto f = std::async(std::launch::async, [&stub]() { stub.Run(); });

  // ClientAsyncWriter<Point, RouteSummary> async_writer;
  auto async_writer = stub.Async_RecordRoute();
  for (int i = 0; i < kPoints; i++) {
    const Feature& f = feature_list[feature_distribution(generator)];
    std::cout << "Visiting point "
              << f.location().latitude()/kCoordFactor << ", "
              << f.location().longitude()/kCoordFactor << std::endl;
    if (!async_writer.Write(f.location())) {
      // Broken stream.
      break;
    }
    RandomSleep();
  }
  // Recv reponse and status.
  async_writer.Close([](const Status& status, const RouteSummary& resp) {
    if (!status.ok()) {
      std::cout << "RecordRoute rpc failed." << std::endl;
      return;
    }
    std::cout << "Finished trip with " << resp.point_count() << " points\n"
              << "Passed " << resp.feature_count() << " features\n"
              << "Traveled " << resp.distance() << " meters\n"
              << "It took " << resp.elapsed_time() << " seconds" << std::endl;
  });

  // Todo: timeout

  stub.Shutdown();
}  // RecordRouteAsync()

void AsyncWriteRouteNotes(Stub::RouteChat_AsyncReaderWriter async_reader_writer) {
  std::vector<RouteNote> notes{
    MakeRouteNote("First message", 0, 0),
    MakeRouteNote("Second message", 0, 1),
    MakeRouteNote("Third message", 1, 0),
    MakeRouteNote("Fourth message", 0, 0)};
  for (const RouteNote& note : notes) {
    std::cout << "Sending message " << note.message()
              << " at " << note.location().latitude() << ", "
              << note.location().longitude() << std::endl;
    async_reader_writer.Write(note);
    RandomSleep();
  }
  async_reader_writer.CloseWriting();  // Optional.
}

void RouteChatAsync(const ChannelSptr& channel) {
  Stub stub(channel);
  auto f_run = std::async(std::launch::async, [&stub]() {
    stub.Run();
  });

  std::atomic_bool bReaderDone = false;
  auto async_reader_writer(
      stub.Async_RouteChat([&bReaderDone](const Status& status) {
        if (!status.ok()) {
          std::cout << "RouteChat rpc failed. " << status.GetDetails()
                    << std::endl;
        }
        bReaderDone = true;
      }));

  async_reader_writer.ReadEach(
      [](const RouteNote& note) { PrintServerNote(note); });
  AsyncWriteRouteNotes(async_reader_writer);

  while (!bReaderDone)
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  stub.Shutdown();  // To break Run().
}  // RouteChatAsync()

void TestRpcTimeout(const ChannelSptr& channel) {
  Stub stub(channel);
  stub.SetCallTimeoutMs(INT64_MIN);
  Point point = MakePoint(0, 0);
  Feature feature;
  Status status = stub.Sync_GetFeature(point, &feature);
  assert(status.GetCode() == GRPC_STATUS_DEADLINE_EXCEEDED);
}

int main(int argc, char** argv) {
  // Expect only arg: --db_path=path/to/route_guide_db.json.
  std::string db = routeguide::GetDbFileContent(argc, argv);
  assert(!db.empty());
  ChannelSptr channel(new Channel("localhost:50051"));
  RouteGuideClient guide(channel, db);

  TestRpcTimeout(channel);

  std::cout << "---- SyncGetFeature --------------" << std::endl;
  guide.SyncGetFeature();
  std::cout << "---- SyncListFeatures --------------" << std::endl;
  guide.SyncListFeatures();
  std::cout << "---- SyncRecordRoute --------------" << std::endl;
  guide.SyncRecordRoute();
  std::cout << "---- SyncRouteChat --------------" << std::endl;
  guide.SyncRouteChat();

  std::cout << "---- GetFeatureAsync ----" << std::endl;
  GetFeatureAsync(channel);
  std::cout << "---- ListFeaturesAsync ----" << std::endl;
  ListFeaturesAsync(channel);
  std::cout << "---- RecordRouteAsnyc ----" << std::endl;
  RecordRouteAsync(channel, db);
  std::cout << "---- RouteChatAsync ---" << std::endl;
  RouteChatAsync(channel);

  return 0;
}
<|endoftext|>


<commit_before>#include "lineedit.h"
#include <qml.h>

LineEditExtension::LineEditExtension(QObject *object)
: QObject(object), m_lineedit(static_cast<QLineEdit *>(object))
{
}

int LineEditExtension::leftMargin() const
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    return l;
}

int LineEditExtension::setLeftMargin(int m)
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    m_lineedit->setTextMargins(m, t, r, b);
}

int LineEditExtension::rightMargin() const
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    return r;
}

int LineEditExtension::setRightMargin(int m)
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    m_lineedit->setTextMargins(l, t, m, b);
}

int LineEditExtension::topMargin() const
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    return t;
}

int LineEditExtension::setTopMargin(int m)
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    m_lineedit->setTextMargins(l, m, r, b);
}

int LineEditExtension::bottomMargin() const
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    return b;
}

int LineEditExtension::setBottomMargin(int m)
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    m_lineedit->setTextMargins(l, t, r, m);
}

QML_DECLARE_TYPE(QLineEdit);
QML_DEFINE_EXTENDED_TYPE(QLineEdit, QLineEdit, LineEditExtension);
<commit_msg>Fix QML_DEFINE_EXTENDED_TYPE use in extending/extended example.<commit_after>#include "lineedit.h"
#include <qml.h>

LineEditExtension::LineEditExtension(QObject *object)
: QObject(object), m_lineedit(static_cast<QLineEdit *>(object))
{
}

int LineEditExtension::leftMargin() const
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    return l;
}

int LineEditExtension::setLeftMargin(int m)
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    m_lineedit->setTextMargins(m, t, r, b);
}

int LineEditExtension::rightMargin() const
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    return r;
}

int LineEditExtension::setRightMargin(int m)
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    m_lineedit->setTextMargins(l, t, m, b);
}

int LineEditExtension::topMargin() const
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    return t;
}

int LineEditExtension::setTopMargin(int m)
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    m_lineedit->setTextMargins(l, m, r, b);
}

int LineEditExtension::bottomMargin() const
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    return b;
}

int LineEditExtension::setBottomMargin(int m)
{
    int l, r, t, b;
    m_lineedit->getTextMargins(&l, &t, &r, &b);
    m_lineedit->setTextMargins(l, t, r, m);
}

QML_DECLARE_TYPE(QLineEdit);
QML_DEFINE_EXTENDED_TYPE(People, 1, 0, 0, QLineEdit, QLineEdit, LineEditExtension);
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: slide.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2007-07-17 15:15:07 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef INCLUDED_SLIDESHOW_SLIDE_HXX
#define INCLUDED_SLIDESHOW_SLIDE_HXX

#include "shapemanager.hxx"
#include "subsettableshapemanager.hxx"
#include "unoviewcontainer.hxx"
#include "slidebitmap.hxx"
#include "shapemaps.hxx"

#include <boost/shared_ptr.hpp>

namespace com {  namespace sun { namespace star {
    namespace drawing {
        class XDrawPage;
    }
    namespace uno {
        class XComponentContext;
    }
    namespace animations {
        class XAnimationNode;
} } } }

namespace basegfx
{
    class B2IVector;
}

/* Definition of Slide interface */

namespace slideshow
{
    namespace internal
    {
        class RGBColor;
        class ScreenUpdater;

        class Slide
        {
        public:
            // Showing
            // -------------------------------------------------------------------

            /** Prepares to show slide.

                Call this method to reduce the timeout show(), and
                getInitialSlideBitmap() need to complete. If
                prefetch() is not called explicitely, the named
                methods will call it implicitely.
             */
            virtual bool prefetch() = 0;

            /** Shows the slide on all registered views

                After this call, the slide will render itself to the
                views, and start its animations.

                @param bSlideBackgoundPainted
                When true, the initial slide content on the background
                layer is already rendered (e.g. from a previous slide
                transition). When false, Slide renders initial content of
                slide.
             */
            virtual bool show( bool bSlideBackgoundPainted ) = 0;

            /** Force-ends the slide

                After this call, the slide has stopped all animations,
                and ceased rendering/visualization on all views.
             */
            virtual void hide() = 0;

            // Queries
            // -------------------------------------------------------------------

            /** Query the size of this slide in user coordinates

                This value is retrieved from the XDrawPage properties.
             */
            virtual basegfx::B2IVector getSlideSize() const = 0;

            /// Gets the underlying API page
            virtual ::com::sun::star::uno::Reference<
                ::com::sun::star::drawing::XDrawPage > getXDrawPage() const = 0;

            /// Gets the animation node.
            virtual ::com::sun::star::uno::Reference<
                ::com::sun::star::animations::XAnimationNode > getXAnimationNode() const = 0;

            // Slide bitmaps
            // -------------------------------------------------------------------

            /** Request bitmap for current slide appearance.

                The bitmap returned by this method depends on the
                current state of the slide and the contained
                animations. A newly generated slide will return the
                initial slide content here (e.g. with all 'appear'
                effect shapes invisible), a slide whose effects are
                currently running will return a bitmap corresponding
                to the current position on the animation timeline, and
                a slide whose effects have all been run will generate
                a bitmap with the final slide appearance (e.g. with
                all 'hide' effect shapes invisible).

                @param rView
                View to retrieve bitmap for (note that the bitmap will
                have device-pixel equivalence to the content that
                would have been rendered onto the given view). Note
                that the view must have been added to this slide
                before via viewAdded().
             */
            virtual SlideBitmapSharedPtr
                getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const = 0;
        };

        typedef ::boost::shared_ptr< Slide > SlideSharedPtr;

        class EventQueue;
        class CursorManager;
        class EventMultiplexer;
        class ActivitiesQueue;
        class UserEventQueue;
        class RGBColor;

        /** Construct from XDrawPage

            The Slide object generally works in XDrawPage model
            coordinates, that is, the page will have the width and
            height as specified in the XDrawPage's property
            set. The top, left corner of the page will be rendered
            at (0,0) in the given canvas' view coordinate system.

            Does not render anything initially

            @param xDrawPage
            Page to display on this slide

            @param xRootNode
            Root of the SMIL animation tree. Used to animate the slide.

            @param rEventQueue
            EventQueue. Used to post events.

            @param rActivitiesQueue
            ActivitiesQueue. Used to run animations.

            @param rEventMultiplexer
            Event source

            @param rUserEventQueue
            UserEeventQueue
        */
        SlideSharedPtr createSlide( const ::com::sun::star::uno::Reference<
                                       ::com::sun::star::drawing::XDrawPage >&         xDrawPage,
                                    const ::com::sun::star::uno::Reference<
                                       ::com::sun::star::animations::XAnimationNode >& xRootNode,
                                    EventQueue&                                        rEventQueue,
                                    EventMultiplexer&                                  rEventMultiplexer,
                                    ScreenUpdater&                                     rScreenUpdater,
                                    ActivitiesQueue&                                   rActivitiesQueue,
                                    UserEventQueue&                                    rUserEventQueue,
                                    CursorManager&                                     rCursorManager,
                                    const UnoViewContainer&                            rViewContainer,
                                    const ::com::sun::star::uno::Reference<
                                       ::com::sun::star::uno::XComponentContext >&     xContext,
                                    const ShapeEventListenerMap&                       rShapeListenerMap,
                                    const ShapeCursorMap&                              rShapeCursorMap,
                                    RGBColor const&                                    aUserPaintColor,
                                    bool                                               bUserPaintEnabled,
                                    bool                                               bIntrinsicAnimationsAllowed,
                                    bool                                               bDisableAnimationZOrder );
    }
}

#endif /* INCLUDED_SLIDESHOW_SLIDE_HXX */
<commit_msg>INTEGRATION: CWS changefileheader (1.9.46); FILE MERGED 2008/03/31 14:00:30 rt 1.9.46.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: slide.hxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_SLIDESHOW_SLIDE_HXX
#define INCLUDED_SLIDESHOW_SLIDE_HXX

#include "shapemanager.hxx"
#include "subsettableshapemanager.hxx"
#include "unoviewcontainer.hxx"
#include "slidebitmap.hxx"
#include "shapemaps.hxx"

#include <boost/shared_ptr.hpp>

namespace com {  namespace sun { namespace star {
    namespace drawing {
        class XDrawPage;
    }
    namespace uno {
        class XComponentContext;
    }
    namespace animations {
        class XAnimationNode;
} } } }

namespace basegfx
{
    class B2IVector;
}

/* Definition of Slide interface */

namespace slideshow
{
    namespace internal
    {
        class RGBColor;
        class ScreenUpdater;

        class Slide
        {
        public:
            // Showing
            // -------------------------------------------------------------------

            /** Prepares to show slide.

                Call this method to reduce the timeout show(), and
                getInitialSlideBitmap() need to complete. If
                prefetch() is not called explicitely, the named
                methods will call it implicitely.
             */
            virtual bool prefetch() = 0;

            /** Shows the slide on all registered views

                After this call, the slide will render itself to the
                views, and start its animations.

                @param bSlideBackgoundPainted
                When true, the initial slide content on the background
                layer is already rendered (e.g. from a previous slide
                transition). When false, Slide renders initial content of
                slide.
             */
            virtual bool show( bool bSlideBackgoundPainted ) = 0;

            /** Force-ends the slide

                After this call, the slide has stopped all animations,
                and ceased rendering/visualization on all views.
             */
            virtual void hide() = 0;

            // Queries
            // -------------------------------------------------------------------

            /** Query the size of this slide in user coordinates

                This value is retrieved from the XDrawPage properties.
             */
            virtual basegfx::B2IVector getSlideSize() const = 0;

            /// Gets the underlying API page
            virtual ::com::sun::star::uno::Reference<
                ::com::sun::star::drawing::XDrawPage > getXDrawPage() const = 0;

            /// Gets the animation node.
            virtual ::com::sun::star::uno::Reference<
                ::com::sun::star::animations::XAnimationNode > getXAnimationNode() const = 0;

            // Slide bitmaps
            // -------------------------------------------------------------------

            /** Request bitmap for current slide appearance.

                The bitmap returned by this method depends on the
                current state of the slide and the contained
                animations. A newly generated slide will return the
                initial slide content here (e.g. with all 'appear'
                effect shapes invisible), a slide whose effects are
                currently running will return a bitmap corresponding
                to the current position on the animation timeline, and
                a slide whose effects have all been run will generate
                a bitmap with the final slide appearance (e.g. with
                all 'hide' effect shapes invisible).

                @param rView
                View to retrieve bitmap for (note that the bitmap will
                have device-pixel equivalence to the content that
                would have been rendered onto the given view). Note
                that the view must have been added to this slide
                before via viewAdded().
             */
            virtual SlideBitmapSharedPtr
                getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const = 0;
        };

        typedef ::boost::shared_ptr< Slide > SlideSharedPtr;

        class EventQueue;
        class CursorManager;
        class EventMultiplexer;
        class ActivitiesQueue;
        class UserEventQueue;
        class RGBColor;

        /** Construct from XDrawPage

            The Slide object generally works in XDrawPage model
            coordinates, that is, the page will have the width and
            height as specified in the XDrawPage's property
            set. The top, left corner of the page will be rendered
            at (0,0) in the given canvas' view coordinate system.

            Does not render anything initially

            @param xDrawPage
            Page to display on this slide

            @param xRootNode
            Root of the SMIL animation tree. Used to animate the slide.

            @param rEventQueue
            EventQueue. Used to post events.

            @param rActivitiesQueue
            ActivitiesQueue. Used to run animations.

            @param rEventMultiplexer
            Event source

            @param rUserEventQueue
            UserEeventQueue
        */
        SlideSharedPtr createSlide( const ::com::sun::star::uno::Reference<
                                       ::com::sun::star::drawing::XDrawPage >&         xDrawPage,
                                    const ::com::sun::star::uno::Reference<
                                       ::com::sun::star::animations::XAnimationNode >& xRootNode,
                                    EventQueue&                                        rEventQueue,
                                    EventMultiplexer&                                  rEventMultiplexer,
                                    ScreenUpdater&                                     rScreenUpdater,
                                    ActivitiesQueue&                                   rActivitiesQueue,
                                    UserEventQueue&                                    rUserEventQueue,
                                    CursorManager&                                     rCursorManager,
                                    const UnoViewContainer&                            rViewContainer,
                                    const ::com::sun::star::uno::Reference<
                                       ::com::sun::star::uno::XComponentContext >&     xContext,
                                    const ShapeEventListenerMap&                       rShapeListenerMap,
                                    const ShapeCursorMap&                              rShapeCursorMap,
                                    RGBColor const&                                    aUserPaintColor,
                                    bool                                               bUserPaintEnabled,
                                    bool                                               bIntrinsicAnimationsAllowed,
                                    bool                                               bDisableAnimationZOrder );
    }
}

#endif /* INCLUDED_SLIDESHOW_SLIDE_HXX */
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/rt/DynamicObject.h"

#include "db/rt/DynamicObjectIterator.h"
#include "db/rt/DynamicObjectIterators.h"

#include <cstdlib>

using namespace db::rt;

DynamicObject::DynamicObject() :
   Collectable<DynamicObjectImpl>(new DynamicObjectImpl())
{
}

DynamicObject::DynamicObject(DynamicObjectImpl* impl) :
   Collectable<DynamicObjectImpl>(impl)
{
}

DynamicObject::DynamicObject(const DynamicObject& rhs) :
   Collectable<DynamicObjectImpl>(rhs)
{
}

DynamicObject::~DynamicObject()
{
}

bool DynamicObject::operator==(const DynamicObject& rhs) const
{
   bool rval;

   const DynamicObject& lhs = *this;
   rval = Collectable<DynamicObjectImpl>::operator==(rhs);
   if(!rval && !lhs.isNull() && !rhs.isNull())
   {
      // compare heap objects
      rval = (*lhs == *rhs);
   }

   return rval;
}

bool DynamicObject::operator!=(const DynamicObject& rhs)
{
   return !(*this == rhs);
}

bool DynamicObject::operator<(const DynamicObject& rhs) const
{
   bool rval;

   const DynamicObject& lhs = *this;

   // NULL is always less than anything other than NULL
   if(lhs.isNull())
   {
      rval = !rhs.isNull();
   }
   // lhs is not NULL, but rhs is, so rhs is not less
   else if(rhs.isNull())
   {
      rval = false;
   }
   // neither lhs or rhs is NULL, compare heap objects
   else
   {
      rval = (*lhs < *rhs);
   }

   return rval;
}

void DynamicObject::operator=(const char* value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(bool value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(int32_t value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(uint32_t value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(int64_t value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(uint64_t value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(double value)
{
   *mReference->ptr = value;
}

DynamicObject& DynamicObject::operator[](const char* name)
{
   return (*mReference->ptr)[name];
}

DynamicObject& DynamicObject::operator[](int index)
{
   return (*mReference->ptr)[index];
}

DynamicObjectIterator DynamicObject::getIterator() const
{
   DynamicObjectIteratorImpl* i;

   switch((*this)->getType())
   {
      case Map:
         i = new DynamicObjectIteratorMap((DynamicObject&)*this);
         break;
      case Array:
         i = new DynamicObjectIteratorArray((DynamicObject&)*this);
         break;
      default:
         i = new DynamicObjectIteratorSingle((DynamicObject&)*this);
         break;
   }

   return DynamicObjectIterator(i);
}

DynamicObject DynamicObject::clone()
{
   DynamicObject rval;

   if(isNull())
   {
      rval.setNull();
   }
   else
   {
      int index = 0;
      rval->setType((*this)->getType());
      DynamicObjectIterator i = getIterator();
      while(i->hasNext())
      {
         DynamicObject dyno = i->next();
         switch((*this)->getType())
         {
            case String:
               rval = dyno->getString();
               break;
            case Boolean:
               rval = dyno->getBoolean();
               break;
            case Int32:
               rval = dyno->getInt32();
               break;
            case UInt32:
               rval = dyno->getUInt32();
               break;
            case Int64:
               rval = dyno->getInt64();
               break;
            case UInt64:
               rval = dyno->getUInt64();
               break;
            case Double:
               rval = dyno->getDouble();
               break;
            case Map:
               rval[i->getName()] = dyno.clone();
               break;
            case Array:
               rval[index++] = dyno.clone();
               break;
         }
      }
   }

   return rval;
}

void DynamicObject::merge(DynamicObject& rhs, bool append)
{
   switch(rhs->getType())
   {
      case String:
      case Boolean:
      case Int32:
      case UInt32:
      case Int64:
      case UInt64:
      case Double:
         *this = rhs.clone();
         break;
      case Map:
      {
         (*this)->setType(Map);
         DynamicObjectIterator i = rhs.getIterator();
         while(i->hasNext())
         {
            DynamicObject next = i->next();
            (*this)[i->getName()].merge(next, append);
         }
         break;
      }
      case Array:
         (*this)->setType(Array);
         DynamicObjectIterator i = rhs.getIterator();
         int offset = (append ? (*this)->length() : 0);
         for(int ii = 0; i->hasNext(); ii++)
         {
            (*this)[offset + ii].merge(i->next(), append);
         }
         break;
   }
}

bool DynamicObject::isSubset(const DynamicObject& rhs) const
{
   bool rval;

   rval = Collectable<DynamicObjectImpl>::operator==(rhs);
   if(!rval && (*this)->getType() == Map && rhs->getType() == Map)
   {
      // ensure right map has same or greater length
      if((*this)->length() <= rhs->length())
      {
         rval = true;
         DynamicObjectIterator i = this->getIterator();
         while(rval && i->hasNext())
         {
            DynamicObject& leftDyno = i->next();
            if(rhs->hasMember(i->getName()))
            {
               DynamicObject& rightDyno = (*rhs)[i->getName()];
               if(leftDyno->getType() == Map && rightDyno->getType() == Map)
               {
                  rval = leftDyno.isSubset(rightDyno);
               }
               else
               {
                  rval = (leftDyno == rightDyno);
               }
            }
            else
            {
               rval = false;
            }
         }
      }
   }

   return rval;
}

const char* DynamicObject::descriptionForType(DynamicObjectType type)
{
   const char* rval;

   switch(type)
   {
      case String:
         rval = "string";
         break;
      case Boolean:
         rval = "boolean";
         break;
      case Int32:
         rval = "32 bit integer";
         break;
      case UInt32:
         rval = "32 bit unsigned integer";
         break;
      case Int64:
         rval = "64 bit integer";
         break;
      case UInt64:
         rval = "64 bit unsigned integer";
         break;
      case Double:
         rval = "floating point";
         break;
      case Map:
         rval = "map";
         break;
      case Array:
         rval = "array";
         break;
   }

   return rval;
}

DynamicObjectType DynamicObject::determineType(const char* str)
{
   DynamicObjectType rval = String;

   // FIXME: this code might interpret hex/octal strings as integers
   // (and other code for that matter!) and we might not want to do that

   // if string starts with whitespace, forget about it
   if(!isspace(str[0]))
   {
      // see if the number is an unsigned int
      // then check signed int
      // then check doubles
      char* end;
      strtoull(str, &end, 10);
      if(end[0] == 0 && str[0] != '-')
      {
         // if end is NULL (and not negative) then the whole string was an int
         rval = UInt64;
      }
      else
      {
         // the number may be a signed int
         strtoll(str, &end, 10);
         if(end[0] == 0)
         {
            // if end is NULL then the whole string was an int
            rval = Int64;
         }
         else
         {
            // the number may be a double
            strtod(str, &end);
            if(end[0] == 0)
            {
               // end is NULL, so we've got a double,
               // else we've assume a String
               rval = Double;
            }
         }
      }
   }

   return rval;
}
<commit_msg>Small optimization.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/rt/DynamicObject.h"

#include "db/rt/DynamicObjectIterator.h"
#include "db/rt/DynamicObjectIterators.h"

#include <cstdlib>

using namespace db::rt;

DynamicObject::DynamicObject() :
   Collectable<DynamicObjectImpl>(new DynamicObjectImpl())
{
}

DynamicObject::DynamicObject(DynamicObjectImpl* impl) :
   Collectable<DynamicObjectImpl>(impl)
{
}

DynamicObject::DynamicObject(const DynamicObject& rhs) :
   Collectable<DynamicObjectImpl>(rhs)
{
}

DynamicObject::~DynamicObject()
{
}

bool DynamicObject::operator==(const DynamicObject& rhs) const
{
   bool rval;

   const DynamicObject& lhs = *this;
   rval = Collectable<DynamicObjectImpl>::operator==(rhs);
   if(!rval && !lhs.isNull() && !rhs.isNull())
   {
      // compare heap objects
      rval = (*lhs == *rhs);
   }

   return rval;
}

bool DynamicObject::operator!=(const DynamicObject& rhs)
{
   return !(*this == rhs);
}

bool DynamicObject::operator<(const DynamicObject& rhs) const
{
   bool rval;

   const DynamicObject& lhs = *this;

   // NULL is always less than anything other than NULL
   if(lhs.isNull())
   {
      rval = !rhs.isNull();
   }
   // lhs is not NULL, but rhs is, so rhs is not less
   else if(rhs.isNull())
   {
      rval = false;
   }
   // neither lhs or rhs is NULL, compare heap objects
   else
   {
      rval = (*lhs < *rhs);
   }

   return rval;
}

void DynamicObject::operator=(const char* value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(bool value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(int32_t value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(uint32_t value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(int64_t value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(uint64_t value)
{
   *mReference->ptr = value;
}

void DynamicObject::operator=(double value)
{
   *mReference->ptr = value;
}

DynamicObject& DynamicObject::operator[](const char* name)
{
   return (*mReference->ptr)[name];
}

DynamicObject& DynamicObject::operator[](int index)
{
   return (*mReference->ptr)[index];
}

DynamicObjectIterator DynamicObject::getIterator() const
{
   DynamicObjectIteratorImpl* i;

   switch((*this)->getType())
   {
      case Map:
         i = new DynamicObjectIteratorMap((DynamicObject&)*this);
         break;
      case Array:
         i = new DynamicObjectIteratorArray((DynamicObject&)*this);
         break;
      default:
         i = new DynamicObjectIteratorSingle((DynamicObject&)*this);
         break;
   }

   return DynamicObjectIterator(i);
}

DynamicObject DynamicObject::clone()
{
   DynamicObject rval;

   if(isNull())
   {
      rval.setNull();
   }
   else
   {
      int index = 0;
      rval->setType((*this)->getType());
      DynamicObjectIterator i = getIterator();
      while(i->hasNext())
      {
         DynamicObject dyno = i->next();
         switch((*this)->getType())
         {
            case String:
               rval = dyno->getString();
               break;
            case Boolean:
               rval = dyno->getBoolean();
               break;
            case Int32:
               rval = dyno->getInt32();
               break;
            case UInt32:
               rval = dyno->getUInt32();
               break;
            case Int64:
               rval = dyno->getInt64();
               break;
            case UInt64:
               rval = dyno->getUInt64();
               break;
            case Double:
               rval = dyno->getDouble();
               break;
            case Map:
               rval[i->getName()] = dyno.clone();
               break;
            case Array:
               rval[index++] = dyno.clone();
               break;
         }
      }
   }

   return rval;
}

void DynamicObject::merge(DynamicObject& rhs, bool append)
{
   switch(rhs->getType())
   {
      case String:
      case Boolean:
      case Int32:
      case UInt32:
      case Int64:
      case UInt64:
      case Double:
         *this = rhs.clone();
         break;
      case Map:
      {
         (*this)->setType(Map);
         DynamicObjectIterator i = rhs.getIterator();
         while(i->hasNext())
         {
            DynamicObject& next = i->next();
            (*this)[i->getName()].merge(next, append);
         }
         break;
      }
      case Array:
         (*this)->setType(Array);
         DynamicObjectIterator i = rhs.getIterator();
         int offset = (append ? (*this)->length() : 0);
         for(int ii = 0; i->hasNext(); ii++)
         {
            (*this)[offset + ii].merge(i->next(), append);
         }
         break;
   }
}

bool DynamicObject::isSubset(const DynamicObject& rhs) const
{
   bool rval;

   rval = Collectable<DynamicObjectImpl>::operator==(rhs);
   if(!rval && (*this)->getType() == Map && rhs->getType() == Map)
   {
      // ensure right map has same or greater length
      if((*this)->length() <= rhs->length())
      {
         rval = true;
         DynamicObjectIterator i = this->getIterator();
         while(rval && i->hasNext())
         {
            DynamicObject& leftDyno = i->next();
            if(rhs->hasMember(i->getName()))
            {
               DynamicObject& rightDyno = (*rhs)[i->getName()];
               if(leftDyno->getType() == Map && rightDyno->getType() == Map)
               {
                  rval = leftDyno.isSubset(rightDyno);
               }
               else
               {
                  rval = (leftDyno == rightDyno);
               }
            }
            else
            {
               rval = false;
            }
         }
      }
   }

   return rval;
}

const char* DynamicObject::descriptionForType(DynamicObjectType type)
{
   const char* rval;

   switch(type)
   {
      case String:
         rval = "string";
         break;
      case Boolean:
         rval = "boolean";
         break;
      case Int32:
         rval = "32 bit integer";
         break;
      case UInt32:
         rval = "32 bit unsigned integer";
         break;
      case Int64:
         rval = "64 bit integer";
         break;
      case UInt64:
         rval = "64 bit unsigned integer";
         break;
      case Double:
         rval = "floating point";
         break;
      case Map:
         rval = "map";
         break;
      case Array:
         rval = "array";
         break;
   }

   return rval;
}

DynamicObjectType DynamicObject::determineType(const char* str)
{
   DynamicObjectType rval = String;

   // FIXME: this code might interpret hex/octal strings as integers
   // (and other code for that matter!) and we might not want to do that

   // if string starts with whitespace, forget about it
   if(!isspace(str[0]))
   {
      // see if the number is an unsigned int
      // then check signed int
      // then check doubles
      char* end;
      strtoull(str, &end, 10);
      if(end[0] == 0 && str[0] != '-')
      {
         // if end is NULL (and not negative) then the whole string was an int
         rval = UInt64;
      }
      else
      {
         // the number may be a signed int
         strtoll(str, &end, 10);
         if(end[0] == 0)
         {
            // if end is NULL then the whole string was an int
            rval = Int64;
         }
         else
         {
            // the number may be a double
            strtod(str, &end);
            if(end[0] == 0)
            {
               // end is NULL, so we've got a double,
               // else we've assume a String
               rval = Double;
            }
         }
      }
   }

   return rval;
}
<|endoftext|>