Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "vectorselectiontool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzTools includes
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
#include "tools/imagegrouping.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/selectioncommandids.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/tselectionhandle.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/imageutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// boost includes
Toshihiro Shimizu 890ddd
#include <boost bind.hpp=""></boost>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
using namespace DragSelectionTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    Global variables
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
VectorSelectionTool l_vectorSelectionTool(TTool::Vectors);
Toshihiro Shimizu 890ddd
TEnv::IntVar l_strokeSelectConstantThickness("SelectionToolConstantThickness", 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const int l_dragThreshold = 10; //!< Distance, in pixels, the user has to
Toshihiro Shimizu 890ddd
								//!  move from a button press to trigger a
Toshihiro Shimizu 890ddd
								//!  selection drag.
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace  stuff
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FourPoints getFourPointsFromVectorImage(
Toshihiro Shimizu 890ddd
	const TVectorImageP &img, const std::set<int> &styleIds, double &maxThickness)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FourPoints p;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (styleIds.empty()) {
Toshihiro Shimizu 890ddd
		p = img->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (UINT i = 0; i < img->getStrokeCount(); i++) {
Toshihiro Shimizu 890ddd
			TStroke *s = img->getStroke(i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (int j = 0; j < s->getControlPointCount(); j++) {
Toshihiro Shimizu 890ddd
				double thick = s->getControlPoint(j).thick;
Toshihiro Shimizu 890ddd
				if (maxThickness < thick)
Toshihiro Shimizu 890ddd
					maxThickness = thick;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		TRectD bbox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (UINT i = 0; i < img->getStrokeCount(); i++) {
Toshihiro Shimizu 890ddd
			TStroke *s = img->getStroke(i);
Toshihiro Shimizu 890ddd
			if (!styleIds.count(s->getStyle()))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (bbox.isEmpty())
Toshihiro Shimizu 890ddd
				bbox = s->getBBox();
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				bbox += s->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (int j = 0; j < s->getControlPointCount(); j++) {
Toshihiro Shimizu 890ddd
				double thick = s->getControlPoint(j).thick;
Toshihiro Shimizu 890ddd
				if (maxThickness < thick)
Toshihiro Shimizu 890ddd
					maxThickness = thick;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		p = bbox;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return p;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool getStrokeIndexFromPos(UINT &index, const TVectorImageP &vi, const TPointD &pos, double pixelSize)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	double t, dist2 = 0;
Toshihiro Shimizu 890ddd
	double maxDist = 5 * pixelSize;
Toshihiro Shimizu 890ddd
	double maxDist2 = maxDist * maxDist;
Toshihiro Shimizu 890ddd
	vi->getNearestStroke(pos, t, index, dist2);
Toshihiro Shimizu 890ddd
	return (dist2 < maxDist2 * 4);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static bool currentOrNotSelected(const VectorSelectionTool &tool, const TFrameId &fid)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return (tool.getCurrentFid() == fid || (tool.isSelectedFramesType() && tool.getSelectedFrames().count(fid) == 0));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline void notifySelectionChanged()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentSelection()->notifySelectionChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    VectorFreeDeformer  implementation
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
VectorFreeDeformer::VectorFreeDeformer(TVectorImageP vi, set<int> strokeIndexes)</int>
Toshihiro Shimizu 890ddd
	: FreeDeformer(), m_vi(vi), m_strokeIndexes(strokeIndexes), m_preserveThickness(false), m_computeRegion(false), m_flip(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRectD r;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	set<int>::iterator it, iEnd = m_strokeIndexes.end();</int>
Toshihiro Shimizu 890ddd
	for (it = m_strokeIndexes.begin(); it != iEnd; ++it) {
Toshihiro Shimizu 890ddd
		TStroke *stroke = m_vi->getStroke(*it);
Toshihiro Shimizu 890ddd
		r += stroke->getBBox();
Toshihiro Shimizu 890ddd
		m_originalStrokes.push_back(new TStroke(*stroke));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_originalP00 = r.getP00();
Toshihiro Shimizu 890ddd
	m_originalP11 = r.getP11();
Toshihiro Shimizu 890ddd
	m_newPoints.push_back(m_originalP00);
Toshihiro Shimizu 890ddd
	m_newPoints.push_back(r.getP10());
Toshihiro Shimizu 890ddd
	m_newPoints.push_back(m_originalP11);
Toshihiro Shimizu 890ddd
	m_newPoints.push_back(r.getP01());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
VectorFreeDeformer::~VectorFreeDeformer()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	clearPointerContainer(m_originalStrokes);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorFreeDeformer::setPreserveThickness(bool preserveThickness)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_preserveThickness = preserveThickness;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorFreeDeformer::setComputeRegion(bool computeRegion)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_computeRegion = computeRegion;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorFreeDeformer::setFlip(bool flip)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_flip = flip;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorFreeDeformer::setPoint(int index, const TPointD &p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_newPoints[index] = p;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorFreeDeformer::setPoints(const TPointD &p0, const TPointD &p1, const TPointD &p2, const TPointD &p3)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_newPoints[0] = p0;
Toshihiro Shimizu 890ddd
	m_newPoints[1] = p1;
Toshihiro Shimizu 890ddd
	m_newPoints[2] = p2;
Toshihiro Shimizu 890ddd
	m_newPoints[3] = p3;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorFreeDeformer::deformRegions()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_strokeIndexes.empty() || !m_computeRegion)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<int> selectedIndexes(</int>
Toshihiro Shimizu 890ddd
		m_strokeIndexes.begin(), m_strokeIndexes.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_vi->notifyChangedStrokes(selectedIndexes, m_originalStrokes, m_flip);
Toshihiro Shimizu 890ddd
	m_computeRegion = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorFreeDeformer::deformImage()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(int(m_strokeIndexes.size()) == int(m_originalStrokes.size()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutexLocker lock(m_vi->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::set<int>::iterator it1 = m_strokeIndexes.begin();</int>
Toshihiro Shimizu 890ddd
	std::vector<tstroke *="">::iterator it2 = m_originalStrokes.begin();</tstroke>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (it1; it1 != m_strokeIndexes.end(); ++it1, ++it2) {
Toshihiro Shimizu 890ddd
		TStroke *stroke = m_vi->getStroke(*it1);
Toshihiro Shimizu 890ddd
		TStroke *originalStroke = *it2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(stroke->getControlPointCount() == originalStroke->getControlPointCount());
Toshihiro Shimizu 890ddd
		int j;
Toshihiro Shimizu 890ddd
		for (j = 0; j < stroke->getControlPointCount(); j++) {
Toshihiro Shimizu 890ddd
			TThickPoint p = deform(originalStroke->getControlPoint(j));
Toshihiro Shimizu 890ddd
			stroke->setControlPoint(j, p);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_computeRegion)
Toshihiro Shimizu 890ddd
		deformRegions();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThickPoint VectorFreeDeformer::deform(TThickPoint point)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double vs = m_originalP11.x - m_originalP00.x;
Toshihiro Shimizu 890ddd
	double s = (vs == 0) ? 0 : (point.x - m_originalP00.x) / vs;
Toshihiro Shimizu 890ddd
	double vt = m_originalP11.y - m_originalP00.y;
Toshihiro Shimizu 890ddd
	double t = (vt == 0) ? 0 : (point.y - m_originalP00.y) / vt;
Toshihiro Shimizu 890ddd
	TPointD A = m_newPoints[0];
Toshihiro Shimizu 890ddd
	TPointD B = m_newPoints[1];
Toshihiro Shimizu 890ddd
	TPointD C = m_newPoints[2];
Toshihiro Shimizu 890ddd
	TPointD D = m_newPoints[3];
Toshihiro Shimizu 890ddd
	TPointD AD = (1 - t) * A + t * D;
Toshihiro Shimizu 890ddd
	TPointD BC = (1 - t) * B + t * C;
Toshihiro Shimizu 890ddd
	TPointD p = (1 - s) * AD + s * BC;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double thickness = point.thick;
Toshihiro Shimizu 890ddd
	if (!m_preserveThickness) {
Toshihiro Shimizu 890ddd
		double eps = 1.e-2;
Toshihiro Shimizu 890ddd
		TPointD p0x = TPointD(p.x - eps, p.x);
Toshihiro Shimizu 890ddd
		TPointD p1x = TPointD(p.x + eps, p.x);
Toshihiro Shimizu 890ddd
		TPointD p0y = TPointD(p.x, p.y - eps);
Toshihiro Shimizu 890ddd
		TPointD p1y = TPointD(p.x, p.y + eps);
Toshihiro Shimizu 890ddd
		m_preserveThickness = true;
Toshihiro Shimizu 890ddd
		TThickPoint newp0x = deform(p0x);
Toshihiro Shimizu 890ddd
		TThickPoint newp1x = deform(p1x);
Toshihiro Shimizu 890ddd
		TThickPoint newp0y = deform(p0y);
Toshihiro Shimizu 890ddd
		TThickPoint newp1y = deform(p1y);
Toshihiro Shimizu 890ddd
		m_preserveThickness = false;
Toshihiro Shimizu 890ddd
		double newA = fabs(cross(newp1x - newp0x, newp1y - newp0y));
Toshihiro Shimizu 890ddd
		double a = 4 * eps * eps;
Toshihiro Shimizu 890ddd
		thickness *= sqrt(newA / a);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TThickPoint(p, thickness);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    UndoChangeStrokes  implementation
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::UndoChangeStrokes::UndoChangeStrokes(
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *level, const TFrameId &frameId, VectorSelectionTool *tool,
Toshihiro Shimizu 890ddd
	const StrokeSelection &selection)
Toshihiro Shimizu 890ddd
	: ToolUtils::TToolUndo(level, frameId), m_tool(tool), m_selectionCount(tool->getSelectionCount()) // Not related to selection
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_oldBBox(tool->getBBox()), m_oldCenter(tool->getCenter()), m_oldDeformValues(tool->m_deformValues), m_newDeformValues(), m_flip(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = m_level->getFrame(m_frameId, false);
Toshihiro Shimizu 890ddd
	if (!vi) {
Toshihiro Shimizu 890ddd
		assert(vi);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const StrokeSelection::IndexesContainer &indexes = selection.getSelection();
Toshihiro Shimizu 890ddd
	m_indexes.assign(indexes.begin(), indexes.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	registerStrokes(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::UndoChangeStrokes::UndoChangeStrokes(
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *level, const TFrameId &frameId, VectorSelectionTool *tool,
Toshihiro Shimizu 890ddd
	const LevelSelection &selection)
Toshihiro Shimizu 890ddd
	: ToolUtils::TToolUndo(level, frameId), m_tool(tool), m_selectionCount(tool->getSelectionCount()) // Not related to selection
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  m_oldBBox(tool->getBBox()), m_oldCenter(tool->getCenter()), m_oldDeformValues(tool->m_deformValues), m_newDeformValues(), m_flip(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = m_level->getFrame(m_frameId, false);
Toshihiro Shimizu 890ddd
	if (!vi) {
Toshihiro Shimizu 890ddd
		assert(vi);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_indexes = getSelectedStrokes(*vi, selection);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	registerStrokes(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::UndoChangeStrokes::~UndoChangeStrokes()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	clearPointerContainer(m_oldStrokes);
Toshihiro Shimizu 890ddd
	clearPointerContainer(m_newStrokes);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::UndoChangeStrokes::registerStrokes(bool beforeModify)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = m_level->getFrame(m_frameId, false);
Toshihiro Shimizu 890ddd
	if (!vi) {
Toshihiro Shimizu 890ddd
		assert(vi);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<tstroke *=""> &strokes = beforeModify ? m_oldStrokes</tstroke>
Toshihiro Shimizu 890ddd
												   : m_newStrokes;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD bbox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int s, sCount = int(m_indexes.size());
Toshihiro Shimizu 890ddd
	for (s = 0; s != sCount; ++s) {
Toshihiro Shimizu 890ddd
		TStroke *stroke = vi->getStroke(m_indexes[s]);
Toshihiro Shimizu 890ddd
		bbox += stroke->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		strokes.push_back(new TStroke(*stroke));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (beforeModify && !bbox.isEmpty()) {
Toshihiro Shimizu 890ddd
		ImageUtils::getFillingInformationOverlappingArea(
Toshihiro Shimizu 890ddd
			vi, m_regionsData, bbox);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		m_newBBox = m_tool->getBBox();
Toshihiro Shimizu 890ddd
		m_newCenter = m_tool->getCenter();
Toshihiro Shimizu 890ddd
		m_newDeformValues = m_tool->m_deformValues;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::UndoChangeStrokes::transform(
Toshihiro Shimizu 890ddd
	const std::vector<tstroke *=""> &strokes, FourPoints bbox,</tstroke>
Toshihiro Shimizu 890ddd
	TPointD center, DragSelectionTool::DeformValues deformValues) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP image = m_level->getFrame(m_frameId, true);
Toshihiro Shimizu 890ddd
	if (!image) {
Toshihiro Shimizu 890ddd
		assert(image);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int s, sCount = int(m_indexes.size());
Toshihiro Shimizu 890ddd
	for (s = 0; s != sCount; ++s) {
Toshihiro Shimizu 890ddd
		int index = m_indexes[s];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TStroke *sourcesStroke = strokes[s],
Toshihiro Shimizu 890ddd
				*stroke = image->getStroke(index);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int cp, cpCount = stroke->getControlPointCount();
Toshihiro Shimizu 890ddd
		for (cp = 0; cp != cpCount; ++cp)
Toshihiro Shimizu 890ddd
			stroke->setControlPoint(cp, sourcesStroke->getControlPoint(cp));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	image->notifyChangedStrokes(m_indexes, strokes, m_flip);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_tool->isSelectionEmpty() && m_selectionCount == m_tool->getSelectionCount()) {
Toshihiro Shimizu 890ddd
		m_tool->setBBox(bbox);
Toshihiro Shimizu 890ddd
		m_tool->setCenter(center);
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		m_tool->computeBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_tool->notifyImageChanged(m_frameId);
Toshihiro Shimizu 890ddd
	m_tool->m_deformValues = deformValues;
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::UndoChangeStrokes::restoreRegions() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = m_level->getFrame(m_frameId, true);
Toshihiro Shimizu 890ddd
	if (!vi) {
Toshihiro Shimizu 890ddd
		assert(vi);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageUtils::assignFillingInformation(*vi, m_regionsData);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::UndoChangeStrokes::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	transform(m_oldStrokes, m_oldBBox, m_oldCenter, m_oldDeformValues);
Toshihiro Shimizu 890ddd
	restoreRegions();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::UndoChangeStrokes::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	transform(m_newStrokes, m_newBBox, m_newCenter, m_newDeformValues);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int DragSelectionTool::UndoChangeStrokes::getSize() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return sizeof(*this) + sizeof(*m_tool);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// UndoChangeOutlineStyle
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoChangeOutlineStyle : public ToolUtils::TToolUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	vector<tstroke::outlineoptions> m_oldOptions, m_newOptions;</tstroke::outlineoptions>
Toshihiro Shimizu 890ddd
	FourPoints m_oldBBox, m_newBBox;
Toshihiro Shimizu 890ddd
	VectorSelectionTool *m_tool;
Toshihiro Shimizu 890ddd
	vector<int> m_indexes;</int>
Toshihiro Shimizu 890ddd
	int m_selectionCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoChangeOutlineStyle(TXshSimpleLevel *level, const TFrameId &frameId, VectorSelectionTool *tool);
Toshihiro Shimizu 890ddd
	~UndoChangeOutlineStyle() {}
Toshihiro Shimizu 890ddd
	void registerStrokes(bool beforeModify = false);
Toshihiro Shimizu 890ddd
	void transform(const std::vector<tstroke::outlineoptions> &options, FourPoints bbox) const;</tstroke::outlineoptions>
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	int getSize() const;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UndoChangeOutlineStyle::UndoChangeOutlineStyle(TXshSimpleLevel *level, const TFrameId &frameId, VectorSelectionTool *tool)
Toshihiro Shimizu 890ddd
	: ToolUtils::TToolUndo(level, frameId), m_tool(tool), m_oldBBox(tool->getBBox()), m_selectionCount(tool->getSelectionCount())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP image = m_level->getFrame(m_frameId, false);
Toshihiro Shimizu 890ddd
	assert(!!image);
Toshihiro Shimizu 890ddd
	if (!image)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	StrokeSelection *strokeSelection = dynamic_cast<strokeselection *="">(tool->getSelection());</strokeselection>
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)image->getStrokeCount(); i++) {
Toshihiro Shimizu 890ddd
		if (!strokeSelection->isSelected(i) && !m_tool->isLevelType() && !m_tool->isSelectedFramesType())
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		m_indexes.push_back(i);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	registerStrokes(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoChangeOutlineStyle::registerStrokes(bool beforeModify)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP image = m_level->getFrame(m_frameId, false);
Toshihiro Shimizu 890ddd
	assert(!!image);
Toshihiro Shimizu 890ddd
	if (!image)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)m_indexes.size(); i++) {
Toshihiro Shimizu 890ddd
		if (beforeModify)
Toshihiro Shimizu 890ddd
			m_oldOptions.push_back(image->getStroke(m_indexes[i])->outlineOptions());
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			m_newOptions.push_back(image->getStroke(m_indexes[i])->outlineOptions());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (!beforeModify)
Toshihiro Shimizu 890ddd
		m_newBBox = m_tool->getBBox();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoChangeOutlineStyle::transform(const std::vector<tstroke::outlineoptions> &options, FourPoints bbox) const</tstroke::outlineoptions>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP image = m_level->getFrame(m_frameId, true);
Toshihiro Shimizu 890ddd
	assert(!!image);
Toshihiro Shimizu 890ddd
	if (!image)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)m_indexes.size(); i++) {
Toshihiro Shimizu 890ddd
		int index = m_indexes[i];
Toshihiro Shimizu 890ddd
		image->getStroke(index)->outlineOptions() = options[i];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (!m_tool->isSelectionEmpty() && m_selectionCount == m_tool->getSelectionCount())
Toshihiro Shimizu 890ddd
		m_tool->setBBox(bbox);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_tool->computeBBox();
Toshihiro Shimizu 890ddd
	m_tool->notifyImageChanged(m_frameId);
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoChangeOutlineStyle::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	transform(m_oldOptions, m_oldBBox);
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoChangeOutlineStyle::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	transform(m_newOptions, m_newBBox);
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int UndoChangeOutlineStyle::getSize() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//NOTE: This is definitely wrong... sizeof(vector) DOES NOT correspond to its
Toshihiro Shimizu 890ddd
	//actual size - as it is internally allocated with new!!
Toshihiro Shimizu 890ddd
	return sizeof(*this) + sizeof(*m_tool);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorDeformTool::VFDScopedBlock
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct VectorDeformTool::VFDScopedBlock //! Type bounding the scope of free deformers in the tool.
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	VFDScopedBlock(SelectionTool *tool) : m_tool(tool)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_tool->setNewFreeDeformer();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	~VFDScopedBlock() { m_tool->clearDeformers(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	SelectionTool *m_tool; //!< [\p external]  Tool owning the deformers.
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorDeformTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::VectorDeformTool::VectorDeformTool(VectorSelectionTool *tool)
Toshihiro Shimizu 890ddd
	: DeformTool(tool), m_undo()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!TTool::getApplication()->getCurrentObject()->isSpline()) {
Toshihiro Shimizu 890ddd
		m_undo.reset(new UndoChangeStrokes(TTool::getApplication()->getCurrentLevel()->getSimpleLevel(),
Toshihiro Shimizu 890ddd
										   tool->getCurrentFid(), tool, tool->strokeSelection()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::VectorDeformTool::~VectorDeformTool()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// DO NOT REMOVE - DESTRUCTS TYPES INCOMPLETE IN THE HEADER
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorDeformTool::applyTransform(FourPoints bbox)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	SelectionTool *tool = getTool();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tcg::unique_ptr<vfdscopedblock> localVfdScopedBlock;</vfdscopedblock>
Toshihiro Shimizu 890ddd
	if (!m_vfdScopedBlock.get()) {
Toshihiro Shimizu 890ddd
		tcg::unique_ptr<vfdscopedblock> &vfdScopedBlock = m_isDragging ? m_vfdScopedBlock : localVfdScopedBlock;</vfdscopedblock>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		vfdScopedBlock.reset(new VFDScopedBlock(tool));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	VectorFreeDeformer *freeDeformer = static_cast<vectorfreedeformer *="">(tool->getFreeDeformer());</vectorfreedeformer>
Toshihiro Shimizu 890ddd
	freeDeformer->setPoints(bbox.getP00(), bbox.getP10(), bbox.getP11(), bbox.getP01());
Toshihiro Shimizu 890ddd
	freeDeformer->setComputeRegion(!m_isDragging);
Toshihiro Shimizu 890ddd
	freeDeformer->setPreserveThickness(tool->isConstantThickness());
Toshihiro Shimizu 890ddd
	freeDeformer->setFlip(isFlip());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!TTool::getApplication()->getCurrentObject()->isSpline() && m_undo.get())
Toshihiro Shimizu 890ddd
		m_undo->setFlip(isFlip());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	freeDeformer->deformImage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tool->invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_isDragging)
Toshihiro Shimizu 890ddd
		tool->notifyImageChanged();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tool->m_deformValues.m_isSelectionModified = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_isDragging && (tool->isLevelType() || tool->isSelectedFramesType()))
Toshihiro Shimizu 890ddd
		transformWholeLevel();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorDeformTool::addTransformUndo()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TTool::getApplication()->getCurrentObject()->isSpline())
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(new UndoPath(getTool()->getXsheet()->getStageObject(getTool()->getObjectId())->getSpline()));
Toshihiro Shimizu 890ddd
	else if (m_undo.get()) {
Toshihiro Shimizu 890ddd
		m_undo->registerStrokes();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(m_undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorDeformTool::transformWholeLevel()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	VectorSelectionTool *tool = dynamic_cast<vectorselectiontool *="">(m_tool);</vectorselectiontool>
Toshihiro Shimizu 890ddd
	assert(tool);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(!tool->levelSelection().isEmpty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<tframeid> fids;</tframeid>
Toshihiro Shimizu 890ddd
	level->getFids(fids);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Remove unwanted fids
Toshihiro Shimizu 890ddd
	fids.erase(std::remove_if(fids.begin(), fids.end(), boost::bind(
Toshihiro Shimizu 890ddd
															::currentOrNotSelected, boost::cref(*tool), _1)),
Toshihiro Shimizu 890ddd
			   fids.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		addTransformUndo(); // For current frame
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int f, fCount = int(fids.size());
Toshihiro Shimizu 890ddd
		for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
			const TFrameId &fid = fids[f];
Toshihiro Shimizu 890ddd
			int t = f + 1; // Current frame's data is always at index 0
Toshihiro Shimizu 890ddd
						   // The others are thus shifted by 1
Toshihiro Shimizu 890ddd
			// Skip nonselected frames
Toshihiro Shimizu 890ddd
			if (tool->getCurrentFid() == fid || (tool->isSelectedFramesType() && tool->getSelectedFrames().count(fid) == 0))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TVectorImageP vi = level->getFrame(fid, true);
Toshihiro Shimizu 890ddd
			if (!vi)
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			tcg::unique_ptr<undochangestrokes> undo(new UndoChangeStrokes(</undochangestrokes>
Toshihiro Shimizu 890ddd
				level, fid, tool, tool->levelSelection()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			std::set<int> strokesIndices;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (int s = 0; s < (int)vi->getStrokeCount(); ++s)
Toshihiro Shimizu 890ddd
				strokesIndices.insert(s);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			FourPoints bbox = tool->getBBox(t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			VectorFreeDeformer *freeDeformer = static_cast<vectorfreedeformer *="">(tool->getFreeDeformer(t));</vectorfreedeformer>
Toshihiro Shimizu 890ddd
			freeDeformer->setPoints(bbox.getPoint(0), bbox.getPoint(1), bbox.getPoint(2), bbox.getPoint(3));
Toshihiro Shimizu 890ddd
			freeDeformer->setComputeRegion(true);
Toshihiro Shimizu 890ddd
			freeDeformer->setPreserveThickness(tool->isConstantThickness());
Toshihiro Shimizu 890ddd
			freeDeformer->setFlip(isFlip());
Toshihiro Shimizu 890ddd
			freeDeformer->deformImage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			undo->registerStrokes();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Finally, notify changed frames
Toshihiro Shimizu 890ddd
	std::for_each(fids.begin(), fids.end(), boost::bind(								  // NOTE: current frame is not here - it should be,
Toshihiro Shimizu 890ddd
												&TTool::notifyImageChanged, m_tool, _1)); //       but it's currently unnecessary, in fact...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// notifyImageChanged(fid) must be invoked OUTSIDE of the loop - since it seems to imply notifyImageChanged()
Toshihiro Shimizu 890ddd
	// on CURRENT image - which seems wrong, but it's too low-level and I'm not changing it.
Toshihiro Shimizu 890ddd
	// This reasonably leads to computeBBox(), but bboxes are taken as INPUT to this transformation...            >:(
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool DragSelectionTool::VectorDeformTool::isFlip()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD scaleValue = getTool()->m_deformValues.m_scaleValue;
Toshihiro Shimizu 890ddd
	return m_startScaleValue.x * scaleValue.x < 0 || m_startScaleValue.y * scaleValue.y < 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorDeformTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	tcg::unique_ptr<vfdscopedblock> vfdScopedBlock(m_vfdScopedBlock.release());</vfdscopedblock>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SelectionTool *tool = getTool();
Toshihiro Shimizu 890ddd
	VectorFreeDeformer *deformer = dynamic_cast<vectorfreedeformer *="">(tool->getFreeDeformer());</vectorfreedeformer>
Toshihiro Shimizu 890ddd
	if (!deformer)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	deformer->setComputeRegion(true);
Toshihiro Shimizu 890ddd
	deformer->setFlip(isFlip());
Toshihiro Shimizu 890ddd
	deformer->deformRegions();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!tool->isLevelType() && !tool->isSelectedFramesType())
Toshihiro Shimizu 890ddd
		addTransformUndo();
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		transformWholeLevel();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_isDragging = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tool->notifyImageChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorRotationTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::VectorRotationTool::VectorRotationTool(VectorSelectionTool *tool)
Toshihiro Shimizu 890ddd
	: VectorDeformTool(tool), m_rotation(new Rotation(this))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorRotationTool::transform(TAffine aff, double angle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	SelectionTool *tool = getTool();
Toshihiro Shimizu 890ddd
	FourPoints newBbox(tool->getBBox() * aff);
Toshihiro Shimizu 890ddd
	TPointD center = m_rotation->getStartCenter();
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < tool->getBBoxsCount(); i++) {
Toshihiro Shimizu 890ddd
		aff = TRotation(center, angle);
Toshihiro Shimizu 890ddd
		tool->setBBox(tool->getBBox(i) * aff, i);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	applyTransform(newBbox);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorRotationTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_rotation->leftButtonDrag(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorRotationTool::draw()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_rotation->draw();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorFreeDeformTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::VectorFreeDeformTool::VectorFreeDeformTool(VectorSelectionTool *tool)
Toshihiro Shimizu 890ddd
	: VectorDeformTool(tool), m_freeDeform(new FreeDeform(this))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorFreeDeformTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_freeDeform->leftButtonDrag(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorMoveSelectionTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::VectorMoveSelectionTool::VectorMoveSelectionTool(VectorSelectionTool *tool)
Toshihiro Shimizu 890ddd
	: VectorDeformTool(tool), m_moveSelection(new MoveSelection(this))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorMoveSelectionTool::transform(TAffine aff)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	SelectionTool *tool = getTool();
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)tool->getBBoxsCount(); i++)
Toshihiro Shimizu 890ddd
		tool->setBBox(tool->getBBox(i) * aff, i);
Toshihiro Shimizu 890ddd
	applyTransform(tool->getBBox());
Toshihiro Shimizu 890ddd
	getTool()->setCenter(aff * tool->getCenter());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorMoveSelectionTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_moveSelection->leftButtonDown(pos, e);
Toshihiro Shimizu 890ddd
	VectorDeformTool::leftButtonDown(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorMoveSelectionTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (norm2(pos - getStartPos()) > l_dragThreshold * getTool()->getPixelSize())
Toshihiro Shimizu 890ddd
		m_moveSelection->leftButtonDrag(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorScaleTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::VectorScaleTool::VectorScaleTool(VectorSelectionTool *tool, int type)
Toshihiro Shimizu 890ddd
	: VectorDeformTool(tool), m_scale(new Scale(this, type))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPointD DragSelectionTool::VectorScaleTool::transform(int index, TPointD newPos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	SelectionTool *tool = getTool();
Toshihiro Shimizu 890ddd
	TPointD scaleValue = tool->m_deformValues.m_scaleValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<fourpoints> startBboxs = m_scale->getStartBboxs();</fourpoints>
Toshihiro Shimizu 890ddd
	TPointD center = m_scale->getStartCenter();
Toshihiro Shimizu 890ddd
	FourPoints bbox = m_scale->bboxScaleInCenter(index, startBboxs[0], newPos, scaleValue, center, true);
Toshihiro Shimizu 890ddd
	if (bbox == startBboxs[0])
Toshihiro Shimizu 890ddd
		return scaleValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool scaleInCenter = m_scale->scaleInCenter();
Toshihiro Shimizu 890ddd
	//Se non ho scalato rispetto al centro calcolo la posizione del nuovo centro
Toshihiro Shimizu 890ddd
	if (!scaleInCenter)
Toshihiro Shimizu 890ddd
		tool->setCenter(m_scale->getNewCenter(index, startBboxs[0], scaleValue));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (tool->isLevelType() || tool->isSelectedFramesType()) {
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 1; i < (int)tool->getBBoxsCount(); i++) {
Toshihiro Shimizu 890ddd
			FourPoints oldBbox = startBboxs[i];
Toshihiro Shimizu 890ddd
			TPointD frameCenter = scaleInCenter ? center : oldBbox.getPoint(getSimmetricPointIndex(index));
Toshihiro Shimizu 890ddd
			TPointD newp = m_scale->getScaledPoint(index, oldBbox, scaleValue, frameCenter);
Toshihiro Shimizu 890ddd
			FourPoints newBbox = m_scale->bboxScaleInCenter(index, oldBbox, newp, scaleValue, frameCenter, false);
Toshihiro Shimizu 890ddd
			tool->setBBox(newBbox, i);
Toshihiro Shimizu 890ddd
			if (!scaleInCenter)
Toshihiro Shimizu 890ddd
				tool->setCenter(m_scale->getNewCenter(index, oldBbox, scaleValue), i);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	tool->setBBox(bbox);
Toshihiro Shimizu 890ddd
	applyTransform(bbox);
Toshihiro Shimizu 890ddd
	return scaleValue;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorScaleTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_scale->leftButtonDown(pos, e);
Toshihiro Shimizu 890ddd
	VectorDeformTool::leftButtonDown(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorScaleTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_scale->leftButtonDrag(pos, e);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorChangeThicknessTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DragSelectionTool::VectorChangeThicknessTool::VectorChangeThicknessTool(VectorSelectionTool *tool)
Toshihiro Shimizu 890ddd
	: DragTool(tool), m_curPos(), m_firstPos(), m_thicknessChange(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = tool->getImage(false);
Toshihiro Shimizu 890ddd
	assert(vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	setStrokesThickness(*vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
	m_undo.reset(new UndoChangeStrokes(level, tool->getCurrentFid(), tool,
Toshihiro Shimizu 890ddd
									   tool->strokeSelection()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
VectorChangeThicknessTool::~VectorChangeThicknessTool()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
namespace SetStrokeThickness
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace DragSelectionTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct Data {
Toshihiro Shimizu 890ddd
	VectorChangeThicknessTool &m_tool;
Toshihiro Shimizu 890ddd
	const TVectorImage &m_vi;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
} // setStrokeThickness
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorChangeThicknessTool::setStrokesThickness(TVectorImage &vi)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static void setThickness(
Toshihiro Shimizu 890ddd
			const SetStrokeThickness::Data &data, int s)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			const TStroke &stroke = *data.m_vi.getStroke(s);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			std::vector<double> strokeThickness;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int cp, cpCount = stroke.getControlPointCount();
Toshihiro Shimizu 890ddd
			strokeThickness.reserve(cpCount);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (cp = 0; cp != cpCount; ++cp)
Toshihiro Shimizu 890ddd
				strokeThickness.push_back(stroke.getControlPoint(cp).thick);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			data.m_tool.m_strokesThickness[s] = strokeThickness;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	}; // locals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SetStrokeThickness::Data data = {*this, vi};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	VectorSelectionTool *vsTool = static_cast<vectorselectiontool *="">(m_tool);</vectorselectiontool>
Toshihiro Shimizu 890ddd
	const LevelSelection &levelSelection = vsTool->levelSelection();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (levelSelection.isEmpty()) {
Toshihiro Shimizu 890ddd
		StrokeSelection *strokeSelection = static_cast<strokeselection *="">(m_tool->getSelection());</strokeselection>
Toshihiro Shimizu 890ddd
		const std::set<int> &selectedStrokeIdxs = strokeSelection->getSelection();</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::for_each(selectedStrokeIdxs.begin(), selectedStrokeIdxs.end(),
Toshihiro Shimizu 890ddd
					  boost::bind(locals::setThickness, boost::cref(data), _1));
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		std::vector<int> strokeIdxs = getSelectedStrokes(vi, levelSelection);</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::for_each(strokeIdxs.begin(), strokeIdxs.end(),
Toshihiro Shimizu 890ddd
					  boost::bind(locals::setThickness, boost::cref(data), _1));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
namespace ChangeImageThickness
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace DragSelectionTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct Data {
Toshihiro Shimizu 890ddd
	VectorChangeThicknessTool &m_tool;
Toshihiro Shimizu 890ddd
	TVectorImage &m_vi;
Toshihiro Shimizu 890ddd
	double m_newThickness;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorChangeThicknessTool::changeImageThickness(TVectorImage &vi, double newThickness)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static void changeThickness(
Toshihiro Shimizu 890ddd
			const ChangeImageThickness::Data &data, int s)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			TStroke &stroke = *data.m_vi.getStroke(s);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (int cp = 0; cp < (int)stroke.getControlPointCount(); ++cp) {
Toshihiro Shimizu 890ddd
				double thickness = tcrop(
Toshihiro Shimizu 890ddd
					data.m_tool.m_strokesThickness[s][cp] + data.m_newThickness,
Toshihiro Shimizu 890ddd
					0.0, 255.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TThickPoint point(TPointD(stroke.getControlPoint(cp)),
Toshihiro Shimizu 890ddd
								  thickness);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				stroke.setControlPoint(cp, point);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	}; // locals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ChangeImageThickness::Data data = {*this, vi, newThickness};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	VectorSelectionTool *vsTool = static_cast<vectorselectiontool *="">(getTool());</vectorselectiontool>
Toshihiro Shimizu 890ddd
	const LevelSelection &levelSelection = vsTool->levelSelection();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (levelSelection.isEmpty()) {
Toshihiro Shimizu 890ddd
		StrokeSelection *strokeSelection = static_cast<strokeselection *="">(m_tool->getSelection());</strokeselection>
Toshihiro Shimizu 890ddd
		const std::set<int> &selectedStrokeIdxs = strokeSelection->getSelection();</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::for_each(selectedStrokeIdxs.begin(), selectedStrokeIdxs.end(),
Toshihiro Shimizu 890ddd
					  boost::bind(locals::changeThickness, boost::ref(data), _1));
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		std::vector<int> strokeIdxs = getSelectedStrokes(vi, levelSelection);</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::for_each(strokeIdxs.begin(), strokeIdxs.end(),
Toshihiro Shimizu 890ddd
					  boost::bind(locals::changeThickness, boost::ref(data), _1));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorChangeThicknessTool::addUndo()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP curVi = getTool()->getImage(true);
Toshihiro Shimizu 890ddd
	if (!curVi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_undo->registerStrokes();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SelectionTool *tool = getTool();
Toshihiro Shimizu 890ddd
	if (tool->isLevelType() || tool->isSelectedFramesType()) {
Toshihiro Shimizu 890ddd
		VectorSelectionTool *vtool = dynamic_cast<vectorselectiontool *="">(tool);</vectorselectiontool>
Toshihiro Shimizu 890ddd
		assert(vtool && !vtool->levelSelection().isEmpty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Retrieve frames available in the level
Toshihiro Shimizu 890ddd
		std::vector<tframeid> fids;</tframeid>
Toshihiro Shimizu 890ddd
		level->getFids(fids);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Remove unwanted frames
Toshihiro Shimizu 890ddd
		fids.erase(std::remove_if(fids.begin(), fids.end(), boost::bind(
Toshihiro Shimizu 890ddd
																::currentOrNotSelected, boost::cref(*vtool), _1)),
Toshihiro Shimizu 890ddd
				   fids.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			// Current frame added separately
Toshihiro Shimizu 890ddd
			TUndoManager::manager()->add(m_undo.release()); // Inside an undo block
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Iterate remaining ones
Toshihiro Shimizu 890ddd
			int f, fCount = int(fids.size());
Toshihiro Shimizu 890ddd
			for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
				const TFrameId &fid = fids[f];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TVectorImageP vi = level->getFrame(fid, true);
Toshihiro Shimizu 890ddd
				if (!vi) {
Toshihiro Shimizu 890ddd
					assert(vi);
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// Transform fid's selection
Toshihiro Shimizu 890ddd
				tcg::unique_ptr<undochangestrokes> undo(new UndoChangeStrokes(</undochangestrokes>
Toshihiro Shimizu 890ddd
					level, fid, vtool, vtool->levelSelection()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				setStrokesThickness(*vi);
Toshihiro Shimizu 890ddd
				changeImageThickness(*vi, m_thicknessChange);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				m_strokesThickness.clear();
Toshihiro Shimizu 890ddd
				undo->registerStrokes();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Finally, notify changed frames
Toshihiro Shimizu 890ddd
		std::for_each(fids.begin(), fids.end(), boost::bind(								  // NOTE: current frame is not here - it was
Toshihiro Shimizu 890ddd
													&TTool::notifyImageChanged, m_tool, _1)); //       aldready notified
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(m_undo.release()); // Outside any undo block
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorChangeThicknessTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_curPos = pos;
Toshihiro Shimizu 890ddd
	m_firstPos = pos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorChangeThicknessTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TAffine aff;
Toshihiro Shimizu 890ddd
	TPointD delta = pos - m_curPos;
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getTool()->getImage(true);
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	m_thicknessChange = (pos.y - m_firstPos.y) * 0.2;
Toshihiro Shimizu 890ddd
	changeImageThickness(*vi, m_thicknessChange);
Toshihiro Shimizu 890ddd
	getTool()->m_deformValues.m_maxSelectionThickness = m_thicknessChange;
Toshihiro Shimizu 890ddd
	getTool()->computeBBox();
Toshihiro Shimizu 890ddd
	getTool()->invalidate();
Toshihiro Shimizu 890ddd
	m_curPos = pos;
Toshihiro Shimizu 890ddd
	getTool()->notifyImageChanged();
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DragSelectionTool::VectorChangeThicknessTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP curVi = getTool()->getImage(true);
Toshihiro Shimizu 890ddd
	if (!curVi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	addUndo();
Toshihiro Shimizu 890ddd
	m_strokesThickness.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool getGroupBBox(const TVectorImage &vi, int strokeIndex, TRectD &gBox)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!vi.isStrokeGrouped(strokeIndex))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	gBox = vi.getStroke(strokeIndex)->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int s, sCount = int(vi.getStrokeCount());
Toshihiro Shimizu 890ddd
	for (s = 0; s != sCount; ++s) {
Toshihiro Shimizu 890ddd
		if (vi.sameGroup(s, strokeIndex))
Toshihiro Shimizu 890ddd
			gBox += vi.getStroke(s)->getBBox();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// UndoEnterGroup
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoEnterGroup : public TUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int m_strokeIndex;
Toshihiro Shimizu 890ddd
	TVectorImageP m_vi;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoEnterGroup(TVectorImageP vi, int strokeIndex)
Toshihiro Shimizu 890ddd
		: m_vi(vi), m_strokeIndex(strokeIndex)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void undo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_vi->exitGroup();
Toshihiro Shimizu 890ddd
		TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void redo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_vi->enterGroup(m_strokeIndex);
Toshihiro Shimizu 890ddd
		TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// UndoExitGroup
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoExitGroup : public TUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int m_strokeIndex;
Toshihiro Shimizu 890ddd
	TVectorImageP m_vi;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoExitGroup(TVectorImageP vi, int strokeIndex)
Toshihiro Shimizu 890ddd
		: m_vi(vi), m_strokeIndex(strokeIndex)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void undo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_vi->enterGroup(m_strokeIndex);
Toshihiro Shimizu 890ddd
		TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void redo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_vi->exitGroup();
Toshihiro Shimizu 890ddd
		TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// VectorSelectionTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
VectorSelectionTool::VectorSelectionTool(int targetType)
Toshihiro Shimizu 890ddd
	: SelectionTool(targetType), m_selectionTarget("Mode:"), m_constantThickness("Preserve Thickness", false), m_levelSelection(m_strokeSelection), m_capStyle("Cap"), m_joinStyle("Join"), m_miterJoinLimit("Miter:", 0, 100, 4), m_selectionCount(0), m_canEnterGroup(true)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (targetType == TTool::Vectors) {
Toshihiro Shimizu 890ddd
#ifndef STUDENT
Toshihiro Shimizu 890ddd
		m_prop.bind(m_selectionTarget);
Toshihiro Shimizu 890ddd
		m_prop.bind(m_constantThickness);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_selectionTarget.addValue(NORMAL_TYPE);
Toshihiro Shimizu 890ddd
		m_selectionTarget.addValue(SELECTED_FRAMES_TYPE);
Toshihiro Shimizu 890ddd
		m_selectionTarget.addValue(ALL_LEVEL_TYPE);
Toshihiro Shimizu 890ddd
		m_selectionTarget.addValue(SAME_STYLE_TYPE);
Toshihiro Shimizu 890ddd
		m_selectionTarget.addValue(STYLE_SELECTED_FRAMES_TYPE);
Toshihiro Shimizu 890ddd
		m_selectionTarget.addValue(STYLE_LEVEL_TYPE);
Toshihiro Shimizu 890ddd
		m_selectionTarget.addValue(BOUNDARY_TYPE);
Toshihiro Shimizu 890ddd
		m_selectionTarget.addValue(BOUNDARY_SELECTED_FRAMES_TYPE);
Toshihiro Shimizu 890ddd
		m_selectionTarget.addValue(BOUNDARY_LEVEL_TYPE);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_strokeSelection.setView(this);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_constantThickness.setId("PreserveThickness");
Toshihiro Shimizu 890ddd
	m_selectionTarget.setId("SelectionMode");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_capStyle.addValue(BUTT_WSTR);
Toshihiro Shimizu 890ddd
	m_capStyle.addValue(ROUNDC_WSTR);
Toshihiro Shimizu 890ddd
	m_capStyle.addValue(PROJECTING_WSTR);
Toshihiro Shimizu 890ddd
	m_capStyle.setId("Cap");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_joinStyle.addValue(MITER_WSTR);
Toshihiro Shimizu 890ddd
	m_joinStyle.addValue(ROUNDJ_WSTR);
Toshihiro Shimizu 890ddd
	m_joinStyle.addValue(BEVEL_WSTR);
Toshihiro Shimizu 890ddd
	m_joinStyle.setId("Join");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_miterJoinLimit.setId("Miter");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_outlineProps.bind(m_capStyle);
Toshihiro Shimizu 890ddd
	m_outlineProps.bind(m_joinStyle);
Toshihiro Shimizu 890ddd
	m_outlineProps.bind(m_miterJoinLimit);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::setNewFreeDeformer()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	clearDeformers();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(true); // BAD: Should not be done at tool creation...
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Current freeDeformer always at index 0
Toshihiro Shimizu 890ddd
	m_freeDeformers.push_back(new VectorFreeDeformer(vi, m_strokeSelection.getSelection()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isLevelType() || isSelectedFramesType()) {
Toshihiro Shimizu 890ddd
		TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// All SELECTED frames' subsequent freeDeformers are stored sequentially after that
Toshihiro Shimizu 890ddd
		std::vector<tframeid> fids;</tframeid>
Toshihiro Shimizu 890ddd
		level->getFids(fids);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fids.erase(std::remove_if(fids.begin(), fids.end(), boost::bind(
Toshihiro Shimizu 890ddd
																::currentOrNotSelected, boost::cref(*this), _1)),
Toshihiro Shimizu 890ddd
				   fids.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::vector<tframeid>::iterator ft, fEnd = fids.end();</tframeid>
Toshihiro Shimizu 890ddd
		for (ft = fids.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
			if (TVectorImageP levelVi = level->getFrame(*ft, false)) {
Toshihiro Shimizu 890ddd
				const std::vector<int> &selectedStrokeIdxs = ::getSelectedStrokes(*levelVi, m_levelSelection);</int>
Toshihiro Shimizu 890ddd
				std::set<int> strokesIndices(selectedStrokeIdxs.begin(), selectedStrokeIdxs.end());</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				m_freeDeformers.push_back(new VectorFreeDeformer(levelVi, strokesIndices));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool VectorSelectionTool::isLevelType() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_levelSelection.framesMode() == LevelSelection::FRAMES_ALL;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool VectorSelectionTool::isSelectedFramesType() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_levelSelection.framesMode() == LevelSelection::FRAMES_SELECTED;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool VectorSelectionTool::isSameStyleType() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_levelSelection.filter() == LevelSelection::SELECTED_STYLES;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool VectorSelectionTool::isModifiableSelectionType() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return (m_levelSelection.isEmpty() || m_levelSelection.filter() == LevelSelection::SELECTED_STYLES);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::updateTranslation()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_selectionTarget.setQStringName(tr("Mode:"));
Toshihiro Shimizu 890ddd
	m_constantThickness.setQStringName(tr("Preserve Thickness"));
Toshihiro Shimizu 890ddd
	m_capStyle.setQStringName(tr("Cap"));
Toshihiro Shimizu 890ddd
	m_joinStyle.setQStringName(tr("Join"));
Toshihiro Shimizu 890ddd
	m_miterJoinLimit.setQStringName(tr("Miter:"));
Toshihiro Shimizu 890ddd
	SelectionTool::updateTranslation();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::updateSelectionTarget()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Make the correct selection current
Toshihiro Shimizu 890ddd
	if (m_selectionTarget.getIndex() == NORMAL_TYPE_IDX) {
Toshihiro Shimizu 890ddd
		std::set<int> selectedStrokes;							// Retain previously selected strokes across</int>
Toshihiro Shimizu 890ddd
		selectedStrokes.swap(m_strokeSelection.getSelection()); // current selection change
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_strokeSelection.makeCurrent(); // Empties any (different) previously current
Toshihiro Shimizu 890ddd
										 // selection on its own
Toshihiro Shimizu 890ddd
		selectedStrokes.swap(m_strokeSelection.getSelection());
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_levelSelection.makeCurrent(); // Same here
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Choose frames mode
Toshihiro Shimizu 890ddd
	LevelSelection::FramesMode framesMode;
Toshihiro Shimizu 890ddd
	switch (m_selectionTarget.getIndex()) {
Toshihiro Shimizu 890ddd
	case SAME_STYLE_TYPE_IDX:
Toshihiro Shimizu 890ddd
	case BOUNDARY_TYPE_IDX:
Toshihiro Shimizu 890ddd
		framesMode = LevelSelection::FRAMES_CURRENT;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		CASE ALL_LEVEL_TYPE_IDX : case STYLE_LEVEL_TYPE_IDX : case BOUNDARY_LEVEL_TYPE_IDX : framesMode = LevelSelection::FRAMES_ALL;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		CASE SELECTED_FRAMES_TYPE_IDX : case STYLE_SELECTED_FRAMES_TYPE_IDX : case BOUNDARY_SELECTED_FRAMES_TYPE_IDX : framesMode = LevelSelection::FRAMES_SELECTED;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (framesMode != m_levelSelection.framesMode())
Toshihiro Shimizu 890ddd
		clearSelectedStrokes();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_levelSelection.framesMode() = framesMode;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Choose filter
Toshihiro Shimizu 890ddd
	LevelSelection::Filter filter;
Toshihiro Shimizu 890ddd
	switch (m_selectionTarget.getIndex()) {
Toshihiro Shimizu 890ddd
	case SELECTED_FRAMES_TYPE_IDX:
Toshihiro Shimizu 890ddd
	case ALL_LEVEL_TYPE_IDX: {
Toshihiro Shimizu 890ddd
		filter = LevelSelection::WHOLE;
Toshihiro Shimizu 890ddd
		selectedStyles().clear();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		CASE SAME_STYLE_TYPE_IDX : case STYLE_SELECTED_FRAMES_TYPE_IDX : case STYLE_LEVEL_TYPE_IDX : filter = LevelSelection::SELECTED_STYLES;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		CASE BOUNDARY_TYPE_IDX : case BOUNDARY_SELECTED_FRAMES_TYPE_IDX : case BOUNDARY_LEVEL_TYPE_IDX:
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			filter = LevelSelection::BOUNDARY_STROKES;
Toshihiro Shimizu 890ddd
			selectedStyles().clear();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (filter != m_levelSelection.filter())
Toshihiro Shimizu 890ddd
		clearSelectedStrokes();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_levelSelection.filter() = filter;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::finalizeSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
	if (vi && !m_levelSelection.isEmpty()) {
Toshihiro Shimizu 890ddd
		std::set<int> &selection = m_strokeSelection.getSelection();</int>
Toshihiro Shimizu 890ddd
		selection.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Apply base additive selection
Toshihiro Shimizu 890ddd
		if (!isSelectedFramesType() || m_selectedFrames.count(getCurrentFid())) {
Toshihiro Shimizu 890ddd
			// Apply filters
Toshihiro Shimizu 890ddd
			std::vector<int> selectedStrokes = getSelectedStrokes(*vi, m_levelSelection);</int>
Toshihiro Shimizu 890ddd
			std::set<int>(selectedStrokes.begin(), selectedStrokes.end()).swap(selection);</int>
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	computeBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentTool()->notifyToolChanged(); // Refreshes toolbar values
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::clearSelectedStrokes()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_strokeSelection.selectNone();
Toshihiro Shimizu 890ddd
	m_levelSelection.styles().clear();
Toshihiro Shimizu 890ddd
	m_deformValues.reset();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::modifySelectionOnClick(TImageP image, const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = TVectorImageP(image);
Toshihiro Shimizu 890ddd
	assert(m_strokeSelection.getImage() == vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	updateSelectionTarget(); // Make selection current. This is necessary in case
Toshihiro Shimizu 890ddd
							 // some other selection context made another selection current.
Toshihiro Shimizu 890ddd
	m_firstPos = m_curPos = pos;
Toshihiro Shimizu 890ddd
	m_selectingRect = FourPoints();
Toshihiro Shimizu 890ddd
	m_selecting = false;
Toshihiro Shimizu 890ddd
	m_justSelected = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	updateAction(pos, e);
Toshihiro Shimizu 890ddd
	if (m_what != Inside && m_what != Outside && m_what != ADD_SELECTION)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT index = 0;
Toshihiro Shimizu 890ddd
	bool modifiableSel = isModifiableSelectionType(),
Toshihiro Shimizu 890ddd
		 strokeAtPos = getStrokeIndexFromPos(index, vi, pos, getPixelSize()),
Toshihiro Shimizu 890ddd
		 addStroke = strokeAtPos && !m_strokeSelection.isSelected(index),
Toshihiro Shimizu 890ddd
		 toggleStroke = strokeAtPos && e.isShiftPressed();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_selecting = (modifiableSel && !strokeAtPos									   // There must be no stroke under cursor
Toshihiro Shimizu 890ddd
				   && (e.isShiftPressed()											   // and either the user is explicitly performing additional selection
Toshihiro Shimizu 890ddd
					   || (m_strokeSelectionType.getIndex() != POLYLINE_SELECTION_IDX) // or the tool support immediate selection on clear
Toshihiro Shimizu 890ddd
					   || m_strokeSelection.isEmpty()));							   // or the strokes list was already cleared
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool clearTargets = !(strokeAtPos || e.isShiftPressed() || m_selecting),
Toshihiro Shimizu 890ddd
		 clearSelection = (addStroke || !strokeAtPos) && !e.isShiftPressed(),
Toshihiro Shimizu 890ddd
		 selectionChanged = clearSelection;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(clearTargets ? clearSelection : true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (clearTargets)
Toshihiro Shimizu 890ddd
		m_levelSelection.selectNone();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (clearSelection) {
Toshihiro Shimizu 890ddd
		m_strokeSelection.selectNone();
Toshihiro Shimizu 890ddd
		selectedStyles().clear(); // Targets are preserved here
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (strokeAtPos)
Toshihiro Shimizu 890ddd
		selectionChanged = m_justSelected = selectStroke(index, toggleStroke);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (selectionChanged) {
Toshihiro Shimizu 890ddd
		m_deformValues.reset(); // Resets selection values shown in the toolbar
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		finalizeSelection();
Toshihiro Shimizu 890ddd
		notifySelectionChanged();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::leftButtonDoubleClick(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_strokeSelectionType.getIndex() == POLYLINE_SELECTION_IDX &&
Toshihiro Shimizu 890ddd
		!m_polyline.empty()) {
Toshihiro Shimizu 890ddd
		closePolyline(pos);
Toshihiro Shimizu 890ddd
		selectRegionVectorImage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_selecting = false;
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int strokeIndex;
Toshihiro Shimizu 890ddd
	if ((strokeIndex = vi->pickGroup(pos)) >= 0) {
Toshihiro Shimizu 890ddd
		if (vi->canEnterGroup(strokeIndex) && m_canEnterGroup) {
Toshihiro Shimizu 890ddd
			if (vi->enterGroup(strokeIndex)) {
Toshihiro Shimizu 890ddd
				clearSelectedStrokes();
Toshihiro Shimizu 890ddd
				TUndoManager::manager()->add(new UndoEnterGroup(vi, strokeIndex));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else if ((strokeIndex = vi->exitGroup()) >= 0)
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(new UndoExitGroup(vi, strokeIndex));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	finalizeSelection();
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_dragTool) {
Toshihiro Shimizu 890ddd
		m_dragTool->leftButtonDrag(pos, e);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double pixelSize = getPixelSize();
Toshihiro Shimizu 890ddd
	TTool::Application *app = TTool::getApplication();
Toshihiro Shimizu 890ddd
	if (!app || m_justSelected || !m_selecting || tdistance2(pos, m_curPos) < 9.0 * pixelSize * pixelSize)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_curPos = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_strokeSelectionType.getIndex() == FREEHAND_SELECTION_IDX)
Toshihiro Shimizu 890ddd
		freehandDrag(pos);
Toshihiro Shimizu 890ddd
	else if (m_strokeSelectionType.getIndex() == RECT_SELECTION_IDX) {
Toshihiro Shimizu 890ddd
		bool selectOverlappingStroke = (m_firstPos.x > pos.x);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRectD rect(m_firstPos, pos);
Toshihiro Shimizu 890ddd
		m_selectingRect = rect;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::set<int> oldSelection;</int>
Toshihiro Shimizu 890ddd
		if (m_shiftPressed)
Toshihiro Shimizu 890ddd
			oldSelection = m_strokeSelection.getSelection();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		clearSelectedStrokes();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_strokeSelection.setImage(vi); // >_<  Shouldn't be done here...?
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bool selectionChanged = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int s, sCount = vi->getStrokeCount();
Toshihiro Shimizu 890ddd
		for (s = 0; s != sCount; ++s) {
Toshihiro Shimizu 890ddd
			if (!vi->isEnteredGroupStroke(s))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TStroke *stroke = vi->getStroke(s);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (m_strokeSelection.isSelected(s))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			bool inSelection = selectOverlappingStroke ? rect.overlaps(stroke->getBBox()) : rect.contains(stroke->getBBox());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (inSelection || (m_shiftPressed && oldSelection.count(s)))
Toshihiro Shimizu 890ddd
				selectionChanged = (selectStroke(s, false) || selectionChanged);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (selectionChanged)
Toshihiro Shimizu 890ddd
			finalizeSelection();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_leftButtonMousePressed = false;
Toshihiro Shimizu 890ddd
	m_shiftPressed = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_dragTool) {
Toshihiro Shimizu 890ddd
		m_dragTool->leftButtonUp(pos, e);
Toshihiro Shimizu 890ddd
		delete m_dragTool;
Toshihiro Shimizu 890ddd
		m_dragTool = 0;
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_selecting)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Complete selection
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (vi) {
Toshihiro Shimizu 890ddd
		if (m_strokeSelectionType.getIndex() == RECT_SELECTION_IDX)
Toshihiro Shimizu 890ddd
			notifySelectionChanged();
Toshihiro Shimizu 890ddd
		else if (m_strokeSelectionType.getIndex() == FREEHAND_SELECTION_IDX) {
Toshihiro Shimizu 890ddd
			QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			closeFreehand(pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (m_stroke->getControlPointCount() > 3)
Toshihiro Shimizu 890ddd
				selectRegionVectorImage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			delete m_stroke; // >:(
Toshihiro Shimizu 890ddd
			m_stroke = 0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_selecting = false;
Toshihiro Shimizu 890ddd
	m_justSelected = false;
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::addContextMenuItems(QMenu *menu)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	menu->addAction(CommandManager::instance()->getAction(MI_RemoveEndpoints));
Toshihiro Shimizu 890ddd
	menu->addSeparator();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_strokeSelection.getGroupCommand()->addMenuItems(menu);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::drawInLevelType(const TVectorImage &vi)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	glPushMatrix();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FourPoints bbox = getBBox();
Toshihiro Shimizu 890ddd
	if (!bbox.isEmpty()) {
Toshihiro Shimizu 890ddd
		TPixel32 frameColor(127, 127, 127);
Toshihiro Shimizu 890ddd
		double pixelSize = getPixelSize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		drawFourPoints(bbox, TPixel32::Black, 0x5555, true);
Toshihiro Shimizu 890ddd
		drawFourPoints(bbox.enlarge(pixelSize * (-4)), frameColor, 0xffff, true);
Toshihiro Shimizu 890ddd
		drawFourPoints(bbox.enlarge(pixelSize * (-2)), frameColor, 0x8888, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		drawCommandHandle(&vi);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	drawSelectedStrokes(vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_selecting && !m_selectingRect.isEmpty())
Toshihiro Shimizu 890ddd
		drawRectSelection(&vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_strokeSelectionType.getIndex() == POLYLINE_SELECTION_IDX)
Toshihiro Shimizu 890ddd
		drawPolylineSelection();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glPopMatrix();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::drawSelectedStrokes(const TVectorImage &vi)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	glEnable(GL_LINE_STIPPLE);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double pixelSize = getPixelSize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int s, sCount = vi.getStrokeCount();
Toshihiro Shimizu 890ddd
	for (s = 0; s != sCount; ++s) {
Toshihiro Shimizu 890ddd
		if (m_strokeSelection.isSelected(s)) {
Toshihiro Shimizu 890ddd
			TStroke *stroke = vi.getStroke(s);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glLineStipple(1, 0xF0F0);
Toshihiro Shimizu 890ddd
			tglColor(TPixel32::Black);
Toshihiro Shimizu 890ddd
			drawStrokeCenterline(*stroke, pixelSize);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glLineStipple(1, 0x0F0F);
Toshihiro Shimizu 890ddd
			tglColor(TPixel32::White);
Toshihiro Shimizu 890ddd
			drawStrokeCenterline(*stroke, pixelSize);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glDisable(GL_LINE_STIPPLE);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::drawGroup(const TVectorImage &vi)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int s, sCount = vi.getStrokeCount();
Toshihiro Shimizu 890ddd
	for (s = 0; s != sCount; ++s) {
Toshihiro Shimizu 890ddd
		if (m_strokeSelection.isSelected(s)) {
Toshihiro Shimizu 890ddd
			TRectD gBox;
Toshihiro Shimizu 890ddd
			if (getGroupBBox(vi, s, gBox))
Toshihiro Shimizu 890ddd
				drawRect(gBox, TPixel::Blue, 0xffff);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::draw()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isLevelType() || isSelectedFramesType()) {
Toshihiro Shimizu 890ddd
		drawInLevelType(*vi);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glPushMatrix();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_strokeSelection.isEmpty())		// o_o  WTF!?
Toshihiro Shimizu 890ddd
		m_bboxs.clear(), m_centers.clear(); //
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// common draw
Toshihiro Shimizu 890ddd
	if (getBBoxsCount() > 0)
Toshihiro Shimizu 890ddd
		drawCommandHandle(vi.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_selecting && !m_selectingRect.isEmpty())
Toshihiro Shimizu 890ddd
		drawRectSelection(vi.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD bbox = vi->getBBox();
Toshihiro Shimizu 890ddd
	TPixel32 frameColor(140, 140, 140);
Toshihiro Shimizu 890ddd
	tglColor(frameColor);
Toshihiro Shimizu 890ddd
	drawRect(bbox, frameColor, 0x5555, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	drawSelectedStrokes(*vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_strokeSelectionType.getIndex() == POLYLINE_SELECTION_IDX)
Toshihiro Shimizu 890ddd
		drawPolylineSelection();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_levelSelection.isEmpty())
Toshihiro Shimizu 890ddd
		drawGroup(*vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glPopMatrix();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSelection *VectorSelectionTool::getSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TImage *image = getImage(false);
Toshihiro Shimizu 890ddd
	TVectorImageP vi = image;
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return &m_strokeSelection;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool VectorSelectionTool::isSelectionEmpty()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false); // We want at least current image to be visible.
Toshihiro Shimizu 890ddd
	if (!vi)							// This is somewhat in line to preventing tool actions
Toshihiro Shimizu 890ddd
		return true;					// on non-visible levels.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return m_strokeSelection.isEmpty(); // Same here, something should be visibly selected.
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::computeBBox()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_bboxs.clear();
Toshihiro Shimizu 890ddd
	m_centers.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isLevelType() || isSelectedFramesType()) {
Toshihiro Shimizu 890ddd
		double maxThickness = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Calculate current image's bbox - it is always the first one (index 0)
Toshihiro Shimizu 890ddd
		if (vi && (isLevelType() || m_selectedFrames.count(getCurrentFid()) > 0)) {
Toshihiro Shimizu 890ddd
			FourPoints bbox = getFourPointsFromVectorImage(vi, selectedStyles(), maxThickness);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			m_bboxs.push_back(bbox);
Toshihiro Shimizu 890ddd
			m_centers.push_back((bbox.getP00() + bbox.getP11()) * 0.5);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// All subsequent SELECTED frames' bboxes come sequentially starting from 1
Toshihiro Shimizu 890ddd
		if (TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel()) {
Toshihiro Shimizu 890ddd
			std::vector<tframeid> fids;</tframeid>
Toshihiro Shimizu 890ddd
			level->getFids(fids);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (int i = 0; i < (int)fids.size(); ++i) {
Toshihiro Shimizu 890ddd
				if (getCurrentFid() == fids[i] || (isSelectedFramesType() && m_selectedFrames.count(fids[i]) == 0))
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TVectorImageP vi = level->getFrame(fids[i], false);
Toshihiro Shimizu 890ddd
				if (!vi)
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				FourPoints p = getFourPointsFromVectorImage(vi, selectedStyles(), maxThickness);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				m_bboxs.push_back(p);
Toshihiro Shimizu 890ddd
				m_centers.push_back(0.5 * (p.getP00() + p.getP11()));
Toshihiro Shimizu 890ddd
				m_deformValues.m_maxSelectionThickness = maxThickness;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else if (vi) {
Toshihiro Shimizu 890ddd
		TRectD newBbox;
Toshihiro Shimizu 890ddd
		double maxThickness = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int i = 0; i < (int)vi->getStrokeCount(); i++) {
Toshihiro Shimizu 890ddd
			TStroke *stroke = vi->getStroke(i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (m_strokeSelection.isSelected(i)) {
Toshihiro Shimizu 890ddd
				newBbox += stroke->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				for (int j = 0; j < stroke->getControlPointCount(); j++) {
Toshihiro Shimizu 890ddd
					double thick = stroke->getControlPoint(j).thick;
Toshihiro Shimizu 890ddd
					if (maxThickness < thick)
Toshihiro Shimizu 890ddd
						maxThickness = thick;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_deformValues.m_maxSelectionThickness = maxThickness;
Toshihiro Shimizu 890ddd
		FourPoints bbox;
Toshihiro Shimizu 890ddd
		bbox = newBbox;
Toshihiro Shimizu 890ddd
		m_bboxs.push_back(bbox);
Toshihiro Shimizu 890ddd
		m_centers.push_back(0.5 * (bbox.getP11() + bbox.getP00()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	++m_selectionCount;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool VectorSelectionTool::selectStroke(int index, bool toggle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
	assert(vi);
Toshihiro Shimizu 890ddd
	assert(m_strokeSelection.getImage() == vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!vi->isEnteredGroupStroke(index)) // If index is not in current group
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (index < 0 || index >= int(vi->getStrokeCount())) // Should be asserted...
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool wasSelected = m_strokeSelection.isSelected(index),
Toshihiro Shimizu 890ddd
		 selectState = !(wasSelected && toggle);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// (De)Select additional strokes related to ours
Toshihiro Shimizu 890ddd
	std::set<int> &selectedStyles = this->selectedStyles();</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isSameStyleType()) // Color selection
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TStroke *refStroke = vi->getStroke(index);
Toshihiro Shimizu 890ddd
		assert(refStroke);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int style = refStroke->getStyle();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (selectState)
Toshihiro Shimizu 890ddd
			selectedStyles.insert(style);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			selectedStyles.erase(style);
Toshihiro Shimizu 890ddd
	} else if (vi->isStrokeGrouped(index) && vi->selectable(index)) // Group selection
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int s, sCount = vi->getStrokeCount();
Toshihiro Shimizu 890ddd
		for (s = 0; s != sCount; ++s) {
Toshihiro Shimizu 890ddd
			if (vi->selectable(s) && vi->sameSubGroup(index, s))
Toshihiro Shimizu 890ddd
				m_strokeSelection.select(s, selectState);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else // Single stroke selection
Toshihiro Shimizu 890ddd
		m_strokeSelection.select(index, selectState);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (selectState != wasSelected);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::onActivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_firstTime) {
Toshihiro Shimizu 890ddd
		m_constantThickness.setValue(l_strokeSelectConstantThickness ? 1 : 0);
Toshihiro Shimizu 890ddd
		m_strokeSelection.setSceneHandle(TTool::getApplication()->getCurrentScene());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SelectionTool::onActivate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::onDeactivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (isLevelType())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SelectionTool::onDeactivate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::doOnActivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
	m_strokeSelection.setImage(vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	updateSelectionTarget();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	finalizeSelection();
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::onImageChanged()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TVectorImageP vi = getImage(false);
Toshihiro Shimizu 890ddd
	TVectorImageP selectedImg = m_strokeSelection.getImage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (vi != selectedImg) {
Toshihiro Shimizu 890ddd
		m_strokeSelection.selectNone();
Toshihiro Shimizu 890ddd
		m_strokeSelection.setImage(vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!(vi && selectedImg)							  // Retain the styles selection ONLY
Toshihiro Shimizu 890ddd
			|| vi->getPalette() != selectedImg->getPalette()) // if palettes still match
Toshihiro Shimizu 890ddd
			selectedStyles().clear();
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		// Remove any eventual stroke index outside the valid range
Toshihiro Shimizu 890ddd
		if (!m_strokeSelection.isEmpty()) {
Toshihiro Shimizu 890ddd
			const std::set<int> &indexes = m_strokeSelection.getSelection();</int>
Toshihiro Shimizu 890ddd
			int strokesCount = selectedImg->getStrokeCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			std::set<int>::const_iterator it;</int>
Toshihiro Shimizu 890ddd
			for (it = indexes.begin(); it != indexes.end(); ++it) {
Toshihiro Shimizu 890ddd
				int index = *it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (index >= strokesCount)
Toshihiro Shimizu 890ddd
					m_strokeSelection.select(index, false);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	finalizeSelection();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::doOnDeactivate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_strokeSelection.selectNone();
Toshihiro Shimizu 890ddd
	m_levelSelection.selectNone();
Toshihiro Shimizu 890ddd
	m_deformValues.reset();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_polyline.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTool::getApplication()->getCurrentSelection()->setSelection(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPropertyGroup *VectorSelectionTool::getProperties(int idx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	switch (idx) {
Toshihiro Shimizu 890ddd
	case 0:
Toshihiro Shimizu 890ddd
		return &m_prop;
Toshihiro Shimizu 890ddd
	case 1:
Toshihiro Shimizu 890ddd
		return &m_outlineProps;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool VectorSelectionTool::onPropertyChanged(string propertyName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (SelectionTool::onPropertyChanged(propertyName))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (propertyName == m_constantThickness.getName())
Toshihiro Shimizu 890ddd
		l_strokeSelectConstantThickness = (int)(m_constantThickness.getValue());
Toshihiro Shimizu 890ddd
	else if (propertyName == m_selectionTarget.getName())
Toshihiro Shimizu 890ddd
		doOnActivate();
Toshihiro Shimizu 890ddd
	else if (propertyName == m_capStyle.getName()) {
Toshihiro Shimizu 890ddd
		if (m_strokeSelection.isEmpty())
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
		UndoChangeOutlineStyle *undo = new UndoChangeOutlineStyle(level, getCurrentFid(), this);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int newCapStyle = m_capStyle.getIndex();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TVectorImageP vi = m_strokeSelection.getImage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const std::set<int> &indices = m_strokeSelection.getSelection();</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::set<int>::iterator it;</int>
Toshihiro Shimizu 890ddd
		for (it = indices.begin(); it != indices.end(); ++it) {
Toshihiro Shimizu 890ddd
			TStroke *stroke = vi->getStroke(*it);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			stroke->outlineOptions().m_capStyle = (TStroke::OutlineOptions::CapStyle)newCapStyle;
Toshihiro Shimizu 890ddd
			stroke->invalidate();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		computeBBox();
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		level->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		undo->registerStrokes();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		notifyImageChanged();
Toshihiro Shimizu 890ddd
	} else if (propertyName == m_joinStyle.getName()) {
Toshihiro Shimizu 890ddd
		if (m_strokeSelection.isEmpty())
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
		UndoChangeOutlineStyle *undo = new UndoChangeOutlineStyle(level, getCurrentFid(), this);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int newJoinStyle = m_joinStyle.getIndex();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TVectorImageP vi = m_strokeSelection.getImage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const std::set<int> &indices = m_strokeSelection.getSelection();</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::set<int>::iterator it;</int>
Toshihiro Shimizu 890ddd
		for (it = indices.begin(); it != indices.end(); ++it) {
Toshihiro Shimizu 890ddd
			TStroke *stroke = vi->getStroke(*it);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			stroke->outlineOptions().m_joinStyle = (TStroke::OutlineOptions::JoinStyle)newJoinStyle;
Toshihiro Shimizu 890ddd
			stroke->invalidate();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		computeBBox();
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		level->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		undo->registerStrokes();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		notifyImageChanged();
Toshihiro Shimizu 890ddd
	} else if (propertyName == m_miterJoinLimit.getName()) {
Toshihiro Shimizu 890ddd
		if (m_strokeSelection.isEmpty())
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
		UndoChangeOutlineStyle *undo = new UndoChangeOutlineStyle(level, getCurrentFid(), this);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int upper = m_miterJoinLimit.getValue();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TVectorImageP vi = m_strokeSelection.getImage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const std::set<int> &indices = m_strokeSelection.getSelection();</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::set<int>::iterator it;</int>
Toshihiro Shimizu 890ddd
		for (it = indices.begin(); it != indices.end(); ++it) {
Toshihiro Shimizu 890ddd
			TStroke *stroke = vi->getStroke(*it);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			stroke->outlineOptions().m_miterUpper = upper;
Toshihiro Shimizu 890ddd
			stroke->invalidate();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		computeBBox();
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		level->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		undo->registerStrokes();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		notifyImageChanged();
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::selectionOutlineStyle(int &capStyle, int &joinStyle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Check the selection's outline style group validity
Toshihiro Shimizu 890ddd
	const std::set<int> &selection = m_strokeSelection.getSelection();</int>
Toshihiro Shimizu 890ddd
	if (selection.empty()) {
Toshihiro Shimizu 890ddd
		capStyle = joinStyle = -1;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP vi = m_strokeSelection.getImage();
Toshihiro Shimizu 890ddd
	const TStroke::OutlineOptions &beginOptions =
Toshihiro Shimizu 890ddd
		vi->getStroke(*selection.begin())->outlineOptions();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	capStyle = beginOptions.m_capStyle;
Toshihiro Shimizu 890ddd
	joinStyle = beginOptions.m_joinStyle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::set<int>::const_iterator it;</int>
Toshihiro Shimizu 890ddd
	for (it = selection.begin(); it != selection.end(); ++it) {
Toshihiro Shimizu 890ddd
		const TStroke::OutlineOptions &options = vi->getStroke(*it)->outlineOptions();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (capStyle != options.m_capStyle)
Toshihiro Shimizu 890ddd
			capStyle = -1;
Toshihiro Shimizu 890ddd
		if (joinStyle != options.m_joinStyle)
Toshihiro Shimizu 890ddd
			joinStyle = -1;
Toshihiro Shimizu 890ddd
		if (capStyle < 0 && joinStyle < 0)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::selectRegionVectorImage()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_stroke)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP vi(getImage(false));
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_strokeSelection.setImage(vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImage selectImg;
Toshihiro Shimizu 890ddd
	selectImg.addStroke(new TStroke(*m_stroke));
Toshihiro Shimizu 890ddd
	selectImg.findRegions();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int sCount = int(vi->getStrokeCount()),
Toshihiro Shimizu 890ddd
		rCount = int(selectImg.getRegionCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool selectionChanged = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int s = 0; s != sCount; ++s) {
Toshihiro Shimizu 890ddd
		TStroke *currentStroke = vi->getStroke(s);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int r = 0; r != rCount; ++r) {
Toshihiro Shimizu 890ddd
			TRegion *region = selectImg.getRegion(r);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (region->contains(*currentStroke, true))
Toshihiro Shimizu 890ddd
				selectionChanged = selectStroke(s, false) || selectionChanged;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (selectionChanged) {
Toshihiro Shimizu 890ddd
		finalizeSelection();
Toshihiro Shimizu 890ddd
		notifySelectionChanged();
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::updateAction(TPointD pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TImageP image = getImage(false);
Toshihiro Shimizu 890ddd
	TVectorImageP vi = (TVectorImageP)image;
Toshihiro Shimizu 890ddd
	if (!vi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SelectionTool::updateAction(pos, e);
Toshihiro Shimizu 890ddd
	if (m_what != Outside || m_cursorId != ToolCursor::StrokeSelectCursor)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FourPoints bbox = getBBox();
Toshihiro Shimizu 890ddd
	UINT index = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((isLevelType() && bbox.contains(pos)) // What about isSelectedFramesType()??
Toshihiro Shimizu 890ddd
		|| (getStrokeIndexFromPos(index, vi, pos, getPixelSize()) && m_strokeSelection.isSelected(index))) {
Toshihiro Shimizu 890ddd
		m_what = Inside;
Toshihiro Shimizu 890ddd
		m_cursorId = isLevelType() ? ToolCursor::LevelSelectCursor
Toshihiro Shimizu 890ddd
								   : ToolCursor::MoveCursor;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void VectorSelectionTool::onSelectedFramesChanged()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (isSelectedFramesType()) // False also in case m_levelSelection is not current
Toshihiro Shimizu 890ddd
		finalizeSelection();
Toshihiro Shimizu 890ddd
}