bool CWKSP_Shapes::_Edit_Shape_Stop(bool bSave)
{
	if( m_Edit_pShape != NULL )
	{
		if( bSave )
		{
			CSG_Shape	*pShape	= Get_Shapes()->Get_Selection(m_Edit_Index);

			if( pShape == NULL )
			{
				Get_Shapes()->Select(pShape = Get_Shapes()->Add_Shape());

				m_Edit_Index	= 0;
			}

			if( pShape != NULL )
			{
				pShape->Assign(m_Edit_pShape, false);
			}
		}

		m_Edit_Shapes.Del_Shapes();
		m_Edit_pShape	= NULL;
		m_Edit_Mode		= EDIT_SHAPE_MODE_Normal;

		Edit_Set_Index(m_Edit_Index);

		Update_Views();

		return( true );
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Shapes::_Edit_Point_Del(void)
{
	if( m_Edit_pShape && m_Edit_iPart >= 0 && m_Edit_iPoint >= 0 )
	{
		if( m_Edit_pShape->Get_Point_Count(m_Edit_iPart) > 1 )
		{
			m_Edit_pShape->Del_Point(m_Edit_iPoint, m_Edit_iPart);

			if( m_Edit_iPoint >= m_Edit_pShape->Get_Point_Count(m_Edit_iPart) )
			{
				m_Edit_iPoint	= m_Edit_pShape->Get_Point_Count(m_Edit_iPart) - 1;
			}

			if( m_Edit_pShape->Get_Point_Count(m_Edit_iPart) <= 1 )
			{
				if( Get_Shapes()->Get_Type() == SHAPE_TYPE_Line || Get_Shapes()->Get_Type() == SHAPE_TYPE_Polygon )
				{
					m_Edit_iPoint	= -1;
				}
			}

			Update_Views(false);

			return( true );
		}
		else
		{
			return( _Edit_Part_Del() );
		}
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Shapes::_Edit_Shape_Del(void)
{
	if( DLG_Message_Confirm(_TL("Delete selected shape(s)."), _TL("Edit Shapes")) )
	{
		if( Get_Shapes()->Get_Selection_Count() > 0 )
		{
			if( m_Edit_pShape )
			{
				_Edit_Shape_Stop(false);

				Get_Shapes()->Del_Shape(Get_Shapes()->Get_Selection(m_Edit_Index));
			}
			else
			{
				Get_Shapes()->Del_Selection();
			}

			Edit_Set_Index(0);

			Update_Views();

			return( true );
		}

		return( _Edit_Shape_Stop(false) );
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Shapes::_Edit_Part_Add(void)
{
	if( m_Edit_pShape )
	{
		m_Edit_iPart	= m_Edit_pShape->Get_Part_Count();
		m_Edit_iPoint	= -1;

		Update_Views(false);

		return( true );
	}

	return( false );
}
//---------------------------------------------------------
void CWKSP_Data_Item::Parameters_Changed(void)
{
	if( !m_bUpdating )
	{
		m_bUpdating	= true;

		On_Parameters_Changed();

		CWKSP_Base_Item::Parameters_Changed();

		m_bUpdating	= false;

		Update_Views(true);
	}
}
//---------------------------------------------------------
bool CWKSP_Shapes::_Edit_Shape_Start(void)
{
	if( m_Edit_pShape == NULL && Get_Shapes()->Get_Selection(m_Edit_Index) != NULL )
	{
		m_Edit_Mode		= EDIT_SHAPE_MODE_Normal;

		m_Edit_pShape	= m_Edit_Shapes.Add_Shape(Get_Shapes()->Get_Selection(m_Edit_Index), SHAPE_COPY_GEOM);

		m_Edit_iPart	= -1;
		m_Edit_iPoint	= -1;

		Update_Views(false);

		return( true );
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Shapes::Edit_Set_Attributes(void)
{
	CSG_Table_Record	*pSelection	= Get_Shapes()->Get_Selection(m_Edit_Index);

	if( pSelection )
	{
		for(int i=0; i<m_Edit_Attributes.Get_Record_Count(); i++)
		{
			if( !pSelection->Set_Value(i, m_Edit_Attributes.Get_Record(i)->asString(1)) )
			{
				m_Edit_Attributes.Get_Record(i)->Set_Value(1, pSelection->asString(i));
			}
		}

		Update_Views(false);

		return( true );
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Shapes::_Edit_Part_Del(void)
{
	if( m_Edit_pShape && m_Edit_iPart >= 0 )
	{
		if( m_Edit_pShape->Get_Part_Count() > 1 )
		{
			m_Edit_pShape->Del_Part(m_Edit_iPart);

			m_Edit_iPart	= -1;
			m_Edit_iPoint	= -1;

			Update_Views(false);

			return( true );
		}
		else
		{
			return( _Edit_Shape_Del() );
		}
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Shapes::_Edit_Merge(void)
{
	if( Get_Shapes()->Get_Selection_Count() < 2 || Get_Shapes()->Get_Type() == SHAPE_TYPE_Point )
	{
		return( false );
	}

	//-----------------------------------------------------
	CSG_Shape	*pMerged	= Get_Shapes()->Get_Selection(0);

	for(int i=1; i<Get_Shapes()->Get_Selection_Count(); i++)
	{
		CSG_Shape	*pShape	= Get_Shapes()->Get_Selection(i);

		for(int iPart=0, jPart=pMerged->Get_Part_Count(); iPart<pShape->Get_Part_Count(); iPart++, jPart++)
		{
			for(int iPoint=0; iPoint<pShape->Get_Point_Count(iPart); iPoint++)
			{
				pMerged->Add_Point(pShape->Get_Point(iPoint, iPart), jPart);
			}
		}
	}

	if( Get_Shapes()->Get_Type() == SHAPE_TYPE_Polygon )
	{
		SG_Polygon_Dissolve(pMerged);
	}

	Get_Shapes()->Select(pMerged, true);
	Get_Shapes()->Del_Selection();
	Get_Shapes()->Select(pMerged, false);

	Update_Views(true);

	return( true );
}
//---------------------------------------------------------
bool CWKSP_Shapes::_Edit_Move(bool bToggle)
{
	if( m_Edit_pShape )
	{
		if( bToggle )
		{
			switch( m_Edit_Mode )
			{
			default:
				break;

			//---------------------------------------------
			case EDIT_SHAPE_MODE_Normal:
				m_Edit_Mode	= EDIT_SHAPE_MODE_Move;

				if( m_Edit_Shapes.Get_Count() > 1 )
				{
					m_Edit_Shapes.Get_Shape(1)->Del_Parts();
				}
				else
				{
					m_Edit_Shapes.Add_Shape();
				}

				return( true );

			//---------------------------------------------
			case EDIT_SHAPE_MODE_Move:
				m_Edit_Mode	= EDIT_SHAPE_MODE_Normal;

				m_Edit_Shapes.Del_Shape(1);

				return( true );
			}
		}

		//-------------------------------------------------
		else // if( !bToggle )
		{
			if( m_Edit_Shapes.Get_Count() > 1 && m_Edit_Shapes.Get_Shape(1)->Get_Point_Count() > 1 )
			{
				CSG_Point	Move	= CSG_Point(m_Edit_Shapes.Get_Shape(1)->Get_Point(1))
									- CSG_Point(m_Edit_Shapes.Get_Shape(1)->Get_Point(0));

				m_Edit_Shapes.Get_Shape(1)->Del_Parts();

				if( SG_Get_Length(Move.Get_X(), Move.Get_Y()) > 0.0 )
				{
					for(int iPart=0; iPart<m_Edit_pShape->Get_Part_Count(); iPart++)
					{
						for(int iPoint=0; iPoint<m_Edit_pShape->Get_Point_Count(iPart); iPoint++)
						{
							m_Edit_pShape->Set_Point(Move + m_Edit_pShape->Get_Point(iPoint, iPart), iPoint, iPart);
						}
					}

					Update_Views(false);

					return( true );
				}
			}
		}
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Shapes::_Edit_Split(void)
{
	if( Get_Shapes()->Get_Type() == SHAPE_TYPE_Polygon
	||  Get_Shapes()->Get_Type() == SHAPE_TYPE_Line )
	{
		switch( m_Edit_Mode )
		{
		default:
			break;

		//-------------------------------------------------
		case EDIT_SHAPE_MODE_Normal:
			m_Edit_Mode	= EDIT_SHAPE_MODE_Split;

			if( m_Edit_Shapes.Get_Count() == 0 )
			{
				m_Edit_Shapes.Add_Shape(Get_Shapes()->Get_Selection());
			}

			if( m_Edit_Shapes.Get_Count() > 1 )
			{
				m_Edit_Shapes.Get_Shape(1)->Del_Parts();
			}
			else
			{
				m_Edit_Shapes.Add_Shape();
			}

			return( true );

		//-------------------------------------------------
		case EDIT_SHAPE_MODE_Split:
			m_Edit_Mode	= EDIT_SHAPE_MODE_Normal;

			CSG_Module	*pModule	= Get_Shapes()->Get_Type() == SHAPE_TYPE_Polygon
			?	SG_Get_Module_Library_Manager().Get_Module(SG_T("shapes_polygons"), 8)	// Polygon-Line Intersection
			:	SG_Get_Module_Library_Manager().Get_Module(SG_T("shapes_lines"   ), 6); // Split Lines with Lines

			if(	pModule )
			{
				CSG_Shapes	Line(SHAPE_TYPE_Line), Split(Get_Shapes()->Get_Type());

				Line.Add_Shape();

				for(int i=0; i<m_Edit_Shapes.Get_Shape(1)->Get_Point_Count(); i++)
				{
					Line.Get_Shape(0)->Add_Point(m_Edit_Shapes.Get_Shape(1)->Get_Point(i));
				}

				m_Edit_Shapes.Del_Shape(1);

				//-----------------------------------------
				bool	bResult;

				CSG_Parameters	P; P.Assign(pModule->Get_Parameters());

				pModule->Set_Manager(NULL);

				if( Get_Shapes()->Get_Type() == SHAPE_TYPE_Polygon )
				{
					bResult	= pModule->Get_Parameters()->Set_Parameter("POLYGONS" , &m_Edit_Shapes)
						&&    pModule->Get_Parameters()->Set_Parameter("LINES"    , &Line)
						&&    pModule->Get_Parameters()->Set_Parameter("INTERSECT", &Split)
						&&    pModule->Execute();
				}
				else //	if( Get_Shapes()->Get_Type() == SHAPE_TYPE_Line )
				{
					bResult	= pModule->Get_Parameters()->Set_Parameter("LINES"    , &m_Edit_Shapes)
						&&    pModule->Get_Parameters()->Set_Parameter("SPLIT"    , &Line)
						&&    pModule->Get_Parameters()->Set_Parameter("INTERSECT", &Split)
						&&    pModule->Execute();
				}

				//-----------------------------------------
				if( bResult )
				{
					if( m_Edit_pShape )
					{
						m_Edit_pShape->Assign(Split.Get_Shape(0), false);

						for(int iSplit=1; iSplit<Split.Get_Count(); iSplit++)
						{
							CSG_Shape	*pSplit	= Split.Get_Shape(iSplit);

							for(int iPart=0; iPart<pSplit->Get_Part_Count(); iPart++)
							{
								for(int iPoint=0, jPart=m_Edit_pShape->Get_Part_Count(); iPoint<pSplit->Get_Point_Count(iPart); iPoint++)
								{
									m_Edit_pShape->Add_Point(pSplit->Get_Point(iPoint, iPart), jPart);
								}
							}
						}
					}
					else if( Get_Shapes()->Get_Selection_Count() == 1 ) // if( !m_Edit_pShape )
					{
						CSG_Shape	*pSelection	= Get_Shapes()->Get_Selection();
						
						pSelection->Assign(Split.Get_Shape(0), false);

						for(int iSplit=1; iSplit<Split.Get_Count(); iSplit++)
						{
							CSG_Shape	*pSplit	= Get_Shapes()->Add_Shape(Split.Get_Shape(iSplit));

							((CSG_Table_Record *)pSplit)->Assign(pSelection);

							Get_Shapes()->Select(pSplit, true);
						}

						m_Edit_Shapes.Del_Shapes();
					}
				}

				pModule->Get_Parameters()->Assign_Values(&P);
				pModule->Set_Manager(P.Get_Manager());
			}

			Update_Views(false);

			return( true );
		}
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Shapes::Edit_On_Mouse_Up(CSG_Point Point, double ClientToWorld, int Key)
{
	//-----------------------------------------------------
	if( Key & MODULE_INTERACTIVE_KEY_RIGHT )
	{
		switch( m_Edit_Mode )
		{
		case EDIT_SHAPE_MODE_Split:
			return( _Edit_Split() );

		case EDIT_SHAPE_MODE_Normal:
			if( m_Edit_pShape && m_Edit_iPart >= 0 && m_Edit_iPoint < 0 )
			{
				m_Edit_iPart	= -1;

				Update_Views(false);

				return( true );
			}
			break;
		}
	}

	//-----------------------------------------------------
	else if( m_Edit_pShape )
	{
		if( m_Edit_Mode == EDIT_SHAPE_MODE_Move )
		{
			if( m_Edit_Shapes.Get_Count() > 1 && m_Edit_Shapes.Get_Shape(1)->Get_Point_Count() > 0 )
			{
				m_Edit_Shapes.Get_Shape(1)->Add_Point(Point);

				return( _Edit_Move(false) );
			}
		}
		else if( m_Edit_iPart >= 0 )
		{
			if( m_Edit_iPoint >= 0 )
			{
				if( Point != m_Edit_Mouse_Down )
				{
					_Edit_Snap_Point(Point, ClientToWorld);

					m_Edit_pShape->Set_Point(Point, m_Edit_iPoint, m_Edit_iPart);

					Update_Views(false);

					return( true );
				}
			}
			else
			{
				_Edit_Snap_Point(Point, ClientToWorld);

				m_Edit_pShape->Add_Point(Point, m_Edit_iPart);

				Update_Views(false);

				return( true );
			}
		}
	}

	//-----------------------------------------------------
	else if( m_Edit_Mode == EDIT_SHAPE_MODE_Normal )
	{
		g_pACTIVE->Get_Attributes()->Save_Changes(true);

		CSG_Rect	rWorld(m_Edit_Mouse_Down, Point);

		if( rWorld.Get_XRange() == 0.0 && rWorld.Get_YRange() == 0.0 )
		{
			rWorld.Inflate(2.0 * ClientToWorld, false);
		}

		int		Count	= Get_Shapes()->Get_Selection_Count();

		Get_Shapes()->Select(rWorld, (Key & MODULE_INTERACTIVE_KEY_CTRL) != 0);

		Edit_Set_Index((Key & MODULE_INTERACTIVE_KEY_CTRL) == 0 ? 0 :
			Count < Get_Shapes()->Get_Selection_Count() || m_Edit_Index >= Get_Shapes()->Get_Selection_Count()
			? Get_Shapes()->Get_Selection_Count() - 1 : m_Edit_Index
		);

		if( m_pTable->Get_View() )
		{
			m_pTable->Get_View()->Update_Selection();
		}

		Update_Views(false);

		return( true );
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Shapes::Edit_On_Mouse_Down(CSG_Point Point, double ClientToWorld, int Key)
{
	CWKSP_Layer::Edit_On_Mouse_Down(Point, ClientToWorld, Key);

	if( !(Key & MODULE_INTERACTIVE_KEY_LEFT) )
	{
		return( false );
	}

	//-----------------------------------------------------
	switch( m_Edit_Mode )
	{
	case EDIT_SHAPE_MODE_Split:
		if( m_Edit_Shapes.Get_Count() > 1 )
		{
			m_Edit_Shapes.Get_Shape(1)->Add_Point(Point);

			Update_Views(false);

			return( true );
		}
		break;

	case EDIT_SHAPE_MODE_Move:
		if( m_Edit_Shapes.Get_Count() > 1 && m_Edit_Shapes.Get_Shape(1)->Get_Point_Count() == 0 )
		{
			m_Edit_Shapes.Get_Shape(1)->Add_Point(Point);

			return( true );
		}
		break;

	case EDIT_SHAPE_MODE_Normal: default:
		if( m_Edit_pShape )
		{
			if( m_Edit_iPart >= 0 && m_Edit_iPoint < 0 )
			{
				// NOP
			}
			else
			{
				int		iPart, iPoint;

				switch( Edit_Shape_HitTest(Point, EDIT_TICKMARK_SIZE * ClientToWorld, iPart, iPoint) )
				{
				//-----------------------------------------
				case 0:	default:
				case 1:
					if( m_Edit_iPart != iPart || m_Edit_iPoint != iPoint )
					{
						m_Edit_iPart	= iPart;
						m_Edit_iPoint	= iPoint;

						Update_Views(false);
					}

					return( true );

				//-----------------------------------------
				case 2:
					m_Edit_pShape->Ins_Point(Point, iPoint, iPart);

					m_Edit_iPart	= iPart;
					m_Edit_iPoint	= iPoint;

					Update_Views(false);

					return( true );
				}
			}
			break;
		}
	}

	//-----------------------------------------------------
	return( false );
}