agg/src/ctrl/agg_scale_ctrl.cpp

455 lines
13 KiB
C++

//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// classes scale_ctrl_impl, scale_ctrl
//
//----------------------------------------------------------------------------
#include "ctrl/agg_scale_ctrl.h"
namespace agg
{
//------------------------------------------------------------------------
scale_ctrl_impl::scale_ctrl_impl(double x1, double y1,
double x2, double y2, bool flip_y) :
ctrl(x1, y1, x2, y2, flip_y),
m_border_thickness(1.0),
m_border_extra((fabs(x2 - x1) > fabs(y2 - y1)) ? (y2 - y1) / 2 : (x2 - x1) / 2),
m_pdx(0.0),
m_pdy(0.0),
m_move_what(move_nothing),
m_value1(0.3),
m_value2(0.7),
m_min_d(0.01)
{
calc_box();
}
//------------------------------------------------------------------------
void scale_ctrl_impl::calc_box()
{
m_xs1 = m_x1 + m_border_thickness;
m_ys1 = m_y1 + m_border_thickness;
m_xs2 = m_x2 - m_border_thickness;
m_ys2 = m_y2 - m_border_thickness;
}
//------------------------------------------------------------------------
void scale_ctrl_impl::border_thickness(double t, double extra)
{
m_border_thickness = t;
m_border_extra = extra;
calc_box();
}
//------------------------------------------------------------------------
void scale_ctrl_impl::resize(double x1, double y1, double x2, double y2)
{
m_x1 = x1;
m_y1 = y1;
m_x2 = x2;
m_y2 = y2;
calc_box();
m_border_extra = (fabs(x2 - x1) > fabs(y2 - y1)) ?
(y2 - y1) / 2 :
(x2 - x1) / 2;
}
//------------------------------------------------------------------------
void scale_ctrl_impl::value1(double value)
{
if(value < 0.0) value = 0.0;
if(value > 1.0) value = 1.0;
if(m_value2 - value < m_min_d) value = m_value2 - m_min_d;
m_value1 = value;
}
//------------------------------------------------------------------------
void scale_ctrl_impl::value2(double value)
{
if(value < 0.0) value = 0.0;
if(value > 1.0) value = 1.0;
if(m_value1 + value < m_min_d) value = m_value1 + m_min_d;
m_value2 = value;
}
//------------------------------------------------------------------------
void scale_ctrl_impl::move(double d)
{
m_value1 += d;
m_value2 += d;
if(m_value1 < 0.0)
{
m_value2 -= m_value1;
m_value1 = 0.0;
}
if(m_value2 > 1.0)
{
m_value1 -= m_value2 - 1.0;
m_value2 = 1.0;
}
}
//------------------------------------------------------------------------
void scale_ctrl_impl::rewind(unsigned idx)
{
m_idx = idx;
switch(idx)
{
default:
case 0: // Background
m_vertex = 0;
m_vx[0] = m_x1 - m_border_extra;
m_vy[0] = m_y1 - m_border_extra;
m_vx[1] = m_x2 + m_border_extra;
m_vy[1] = m_y1 - m_border_extra;
m_vx[2] = m_x2 + m_border_extra;
m_vy[2] = m_y2 + m_border_extra;
m_vx[3] = m_x1 - m_border_extra;
m_vy[3] = m_y2 + m_border_extra;
break;
case 1: // Border
m_vertex = 0;
m_vx[0] = m_x1;
m_vy[0] = m_y1;
m_vx[1] = m_x2;
m_vy[1] = m_y1;
m_vx[2] = m_x2;
m_vy[2] = m_y2;
m_vx[3] = m_x1;
m_vy[3] = m_y2;
m_vx[4] = m_x1 + m_border_thickness;
m_vy[4] = m_y1 + m_border_thickness;
m_vx[5] = m_x1 + m_border_thickness;
m_vy[5] = m_y2 - m_border_thickness;
m_vx[6] = m_x2 - m_border_thickness;
m_vy[6] = m_y2 - m_border_thickness;
m_vx[7] = m_x2 - m_border_thickness;
m_vy[7] = m_y1 + m_border_thickness;
break;
case 2: // pointer1
if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
{
m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value1,
(m_ys1 + m_ys2) / 2.0,
m_y2 - m_y1,
m_y2 - m_y1,
32);
}
else
{
m_ellipse.init((m_xs1 + m_xs2) / 2.0,
m_ys1 + (m_ys2 - m_ys1) * m_value1,
m_x2 - m_x1,
m_x2 - m_x1,
32);
}
m_ellipse.rewind(0);
break;
case 3: // pointer2
if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
{
m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value2,
(m_ys1 + m_ys2) / 2.0,
m_y2 - m_y1,
m_y2 - m_y1,
32);
}
else
{
m_ellipse.init((m_xs1 + m_xs2) / 2.0,
m_ys1 + (m_ys2 - m_ys1) * m_value2,
m_x2 - m_x1,
m_x2 - m_x1,
32);
}
m_ellipse.rewind(0);
break;
case 4: // slider
m_vertex = 0;
if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
{
m_vx[0] = m_xs1 + (m_xs2 - m_xs1) * m_value1;
m_vy[0] = m_y1 - m_border_extra / 2.0;
m_vx[1] = m_xs1 + (m_xs2 - m_xs1) * m_value2;
m_vy[1] = m_vy[0];
m_vx[2] = m_vx[1];
m_vy[2] = m_y2 + m_border_extra / 2.0;
m_vx[3] = m_vx[0];
m_vy[3] = m_vy[2];
}
else
{
m_vx[0] = m_x1 - m_border_extra / 2.0;
m_vy[0] = m_ys1 + (m_ys2 - m_ys1) * m_value1;
m_vx[1] = m_vx[0];
m_vy[1] = m_ys1 + (m_ys2 - m_ys1) * m_value2;
m_vx[2] = m_x2 + m_border_extra / 2.0;
m_vy[2] = m_vy[1];
m_vx[3] = m_vx[2];
m_vy[3] = m_vy[0];
}
break;
}
}
//------------------------------------------------------------------------
unsigned scale_ctrl_impl::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_line_to;
switch(m_idx)
{
case 0:
case 4:
if(m_vertex == 0) cmd = path_cmd_move_to;
if(m_vertex >= 4) cmd = path_cmd_stop;
*x = m_vx[m_vertex];
*y = m_vy[m_vertex];
m_vertex++;
break;
case 1:
if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to;
if(m_vertex >= 8) cmd = path_cmd_stop;
*x = m_vx[m_vertex];
*y = m_vy[m_vertex];
m_vertex++;
break;
case 2:
case 3:
cmd = m_ellipse.vertex(x, y);
break;
default:
cmd = path_cmd_stop;
break;
}
if(!is_stop(cmd))
{
transform_xy(x, y);
}
return cmd;
}
//------------------------------------------------------------------------
bool scale_ctrl_impl::in_rect(double x, double y) const
{
inverse_transform_xy(&x, &y);
return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2;
}
//------------------------------------------------------------------------
bool scale_ctrl_impl::on_mouse_button_down(double x, double y)
{
inverse_transform_xy(&x, &y);
double xp1;
double xp2;
double ys1;
double ys2;
double xp;
double yp;
if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
{
xp1 = m_xs1 + (m_xs2 - m_xs1) * m_value1;
xp2 = m_xs1 + (m_xs2 - m_xs1) * m_value2;
ys1 = m_y1 - m_border_extra / 2.0;
ys2 = m_y2 + m_border_extra / 2.0;
yp = (m_ys1 + m_ys2) / 2.0;
if(x > xp1 && y > ys1 && x < xp2 && y < ys2)
{
m_pdx = xp1 - x;
m_move_what = move_slider;
return true;
}
//if(x < xp1 && calc_distance(x, y, xp1, yp) <= m_y2 - m_y1)
if(calc_distance(x, y, xp1, yp) <= m_y2 - m_y1)
{
m_pdx = xp1 - x;
m_move_what = move_value1;
return true;
}
//if(x > xp2 && calc_distance(x, y, xp2, yp) <= m_y2 - m_y1)
if(calc_distance(x, y, xp2, yp) <= m_y2 - m_y1)
{
m_pdx = xp2 - x;
m_move_what = move_value2;
return true;
}
}
else
{
xp1 = m_x1 - m_border_extra / 2.0;
xp2 = m_x2 + m_border_extra / 2.0;
ys1 = m_ys1 + (m_ys2 - m_ys1) * m_value1;
ys2 = m_ys1 + (m_ys2 - m_ys1) * m_value2;
xp = (m_xs1 + m_xs2) / 2.0;
if(x > xp1 && y > ys1 && x < xp2 && y < ys2)
{
m_pdy = ys1 - y;
m_move_what = move_slider;
return true;
}
//if(y < ys1 && calc_distance(x, y, xp, ys1) <= m_x2 - m_x1)
if(calc_distance(x, y, xp, ys1) <= m_x2 - m_x1)
{
m_pdy = ys1 - y;
m_move_what = move_value1;
return true;
}
//if(y > ys2 && calc_distance(x, y, xp, ys2) <= m_x2 - m_x1)
if(calc_distance(x, y, xp, ys2) <= m_x2 - m_x1)
{
m_pdy = ys2 - y;
m_move_what = move_value2;
return true;
}
}
return false;
}
//------------------------------------------------------------------------
bool scale_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
{
inverse_transform_xy(&x, &y);
if(!button_flag)
{
return on_mouse_button_up(x, y);
}
double xp = x + m_pdx;
double yp = y + m_pdy;
double dv;
switch(m_move_what)
{
case move_value1:
if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
{
m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1);
}
else
{
m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1);
}
if(m_value1 < 0.0) m_value1 = 0.0;
if(m_value1 > m_value2 - m_min_d) m_value1 = m_value2 - m_min_d;
return true;
case move_value2:
if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
{
m_value2 = (xp - m_xs1) / (m_xs2 - m_xs1);
}
else
{
m_value2 = (yp - m_ys1) / (m_ys2 - m_ys1);
}
if(m_value2 > 1.0) m_value2 = 1.0;
if(m_value2 < m_value1 + m_min_d) m_value2 = m_value1 + m_min_d;
return true;
case move_slider:
dv = m_value2 - m_value1;
if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
{
m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1);
}
else
{
m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1);
}
m_value2 = m_value1 + dv;
if(m_value1 < 0.0)
{
dv = m_value2 - m_value1;
m_value1 = 0.0;
m_value2 = m_value1 + dv;
}
if(m_value2 > 1.0)
{
dv = m_value2 - m_value1;
m_value2 = 1.0;
m_value1 = m_value2 - dv;
}
return true;
default:
return false;
}
}
//------------------------------------------------------------------------
bool scale_ctrl_impl::on_mouse_button_up(double, double)
{
m_move_what = move_nothing;
return false;
}
//------------------------------------------------------------------------
bool scale_ctrl_impl::on_arrow_keys(bool /*left*/, bool /*right*/, bool /*down*/, bool /*up*/)
{
/*
if(right || up)
{
m_value += 0.005;
if(m_value > 1.0) m_value = 1.0;
return true;
}
if(left || down)
{
m_value -= 0.005;
if(m_value < 0.0) m_value = 0.0;
return true;
}
*/
return false;
}
}