Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/fxcommand.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
#include "toonz/fxdag.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfxset.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshzeraryfxcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjecttree.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshpalettecolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tfxhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tscenehandle.h"
Toshihiro Shimizu 890ddd
#include "historytypes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tparamcontainer.h"
Toshihiro Shimizu 890ddd
#include "tparamset.h"
Toshihiro Shimizu 890ddd
#include "tfxattributes.h"
Toshihiro Shimizu 890ddd
#include "tmacrofx.h"
Toshihiro Shimizu 890ddd
#include "tpassivecachemanager.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
#include "tconst.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qmap></qmap>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_macros.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_base.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_function_types.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_iterator_ops.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  Toonz currently has THREE different APIs to deal with scene objects commands:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    1. From the xsheet, see columncommand.cpp
Toshihiro Shimizu 890ddd
    2. From the stage schematic
Toshihiro Shimizu 890ddd
    3. From the fx schematic
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  *This* is the one version that should 'rule them all' - we still have to
Toshihiro Shimizu 890ddd
  unify them, though.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TODO:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  - Associated Stage Object copies when copying columns
Toshihiro Shimizu 890ddd
  - Stage schematic currently ignored (eg delete columns undo)
Toshihiro Shimizu 890ddd
  - Double-check macro fxs behavior
Toshihiro Shimizu 890ddd
  - Double-check group behavior
Toshihiro Shimizu 890ddd
  - Enforce dynamic link groups consistency
Toshihiro Shimizu 890ddd
*/
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
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline TFx *getActualIn(TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(fx);</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
	return zcfx ? (assert(zcfx->getZeraryFx()), zcfx->getZeraryFx()) : fx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline TFx *getActualOut(TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TZeraryFx *zfx = dynamic_cast<tzeraryfx *="">(fx);</tzeraryfx>
Toshihiro Shimizu 890ddd
	return (zfx && zfx->getColumnFx()) ? zfx->getColumnFx() : fx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline int inputPortIndex(TFx *fx, TFxPort *port)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int p, pCount = fx->getInputPortCount();
Toshihiro Shimizu 890ddd
	for (p = 0; p != pCount; ++p)
Toshihiro Shimizu 890ddd
		if (fx->getInputPort(p) == port)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
	return p;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Returns whether the specified fx is internal to a macro fx. Fxs
Toshihiro Shimizu 890ddd
  inside a macro should not be affected by most editing commands - the
Toshihiro Shimizu 890ddd
  macro is required to be exploded first.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
bool isInsideAMacroFx(TFx *fx, TXsheet *xsh)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!fx)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TColumnFx *cfx = dynamic_cast<tcolumnfx *="">(fx);</tcolumnfx>
Toshihiro Shimizu 890ddd
	TXsheetFx *xfx = dynamic_cast<txsheetfx *="">(fx);</txsheetfx>
Toshihiro Shimizu 890ddd
	TOutputFx *ofx = dynamic_cast<toutputfx *="">(fx);</toutputfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return !cfx && !xfx && !ofx &&
Toshihiro Shimizu 890ddd
		   !(xsh->getFxDag()->getInternalFxs()->containsFx(fx));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename paramcont=""></typename>
Toshihiro Shimizu 890ddd
void setParamsToCurrentScene(TXsheet *xsh, const ParamCont *cont)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (int p = 0; p != cont->getParamCount(); ++p) {
Toshihiro Shimizu 890ddd
		TParam ¶m = *cont->getParam(p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (TDoubleParam *dp = dynamic_cast<tdoubleparam *="">(¶m))</tdoubleparam>
Toshihiro Shimizu 890ddd
			xsh->getStageObjectTree()->setGrammar(dp);
Toshihiro Shimizu 890ddd
		else if (TParamSet *paramSet = dynamic_cast<tparamset *="">(¶m))</tparamset>
Toshihiro Shimizu 890ddd
			setParamsToCurrentScene(xsh, paramSet);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline void setFxParamToCurrentScene(TFx *fx, TXsheet *xsh)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	setParamsToCurrentScene(xsh, fx->getParams());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void initializeFx(TXsheet *xsh, TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(fx))</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		fx = zcfx->getZeraryFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	xsh->getFxDag()->assignUniqueId(fx);
Toshihiro Shimizu 890ddd
	setFxParamToCurrentScene(fx, xsh);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void showFx(TXsheet *xsh, TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	fx->getAttributes()->setIsOpened(xsh->getFxDag()->getDagGridDimension() == 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(fx))</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		fx = zcfx->getZeraryFx();
Toshihiro Shimizu 890ddd
	fx->getAttributes()->passiveCacheDataIdx() = -1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void hideFx(TXsheet *xsh, TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(fx))</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		fx = zcfx->getZeraryFx();
Toshihiro Shimizu 890ddd
	TPassiveCacheManager::instance()->disableCache(fx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void addFxToCurrentScene(TFx *fx, TXsheet *xsh, bool isNewFx = true)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (isNewFx)
Toshihiro Shimizu 890ddd
		initializeFx(xsh, fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	xsh->getFxDag()->getInternalFxs()->addFx(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	showFx(xsh, fx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void removeFxFromCurrentScene(TFx *fx, TXsheet *xsh)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	xsh->getFxDag()->getInternalFxs()->removeFx(fx);
Toshihiro Shimizu 890ddd
	xsh->getFxDag()->getTerminalFxs()->removeFx(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	hideFx(xsh, fx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Filter Functors  definition
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct FilterInsideAMacro {
Toshihiro Shimizu 890ddd
	TXsheet *m_xsh;
Toshihiro Shimizu 890ddd
	inline bool operator()(const TFxP &fx)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return ::isInsideAMacroFx(fx.getPointer(), m_xsh);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inline bool operator()(const TFxCommand::Link &link)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return ::isInsideAMacroFx(link.m_inputFx.getPointer(), m_xsh) ||
Toshihiro Shimizu 890ddd
			   ::isInsideAMacroFx(link.m_outputFx.getPointer(), m_xsh);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct FilterNonTerminalFxs {
Toshihiro Shimizu 890ddd
	TXsheet *xsh;
Toshihiro Shimizu 890ddd
	inline bool operator()(const TFxP &fx)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return !xsh->getFxDag()->getTerminalFxs()->containsFx(fx.getPointer());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct FilterTerminalFxs {
Toshihiro Shimizu 890ddd
	TXsheet *xsh;
Toshihiro Shimizu 890ddd
	inline bool operator()(const TFxP &fx)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return xsh->getFxDag()->getTerminalFxs()->containsFx(fx.getPointer());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct FilterColumnFxs {
Toshihiro Shimizu 890ddd
	inline bool operator()(const TFxP &fx) { return dynamic_cast<tlevelcolumnfx *="">(fx.getPointer()); }</tlevelcolumnfx>
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    CloneFxFunctor  definition
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct CloneFxFunctor {
Toshihiro Shimizu 890ddd
	TFxP m_src;
Toshihiro Shimizu 890ddd
	bool m_ownsSrc;
Toshihiro Shimizu 890ddd
	TFx *operator()()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_ownsSrc)
Toshihiro Shimizu 890ddd
			m_ownsSrc = false; // Transfer m_src and ownership if it
Toshihiro Shimizu 890ddd
		else				   // was surrendered
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			assert(m_src->getRefCount() > 1); // We'll be linking params to the cloned
Toshihiro Shimizu 890ddd
											  // fx - so it MUST NOT be destroyed on release
Toshihiro Shimizu 890ddd
			TFx *src = m_src.getPointer();
Toshihiro Shimizu 890ddd
			m_src = m_src->clone(false); // Duplicate and link parameters all
Toshihiro Shimizu 890ddd
			m_src->linkParams(src);		 // the following times
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return m_src.getPointer();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    FxCommandUndo  definition
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class FxCommandUndo : public TUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	virtual ~FxCommandUndo() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	virtual bool isConsistent() const = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	template <typename pred=""></typename>
Toshihiro Shimizu 890ddd
	static TFx *leftmostConnectedFx(TFx *fx, Pred pred);
Toshihiro Shimizu 890ddd
	template <typename pred=""></typename>
Toshihiro Shimizu 890ddd
	static TFx *rightmostConnectedFx(TFx *fx, Pred pred);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static TFx *leftmostConnectedFx(TFx *fx);
Toshihiro Shimizu 890ddd
	static TFx *rightmostConnectedFx(TFx *fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static std::vector<tfxcommand::link> inputLinks(TXsheet *xsh, TFx *fx);</tfxcommand::link>
Toshihiro Shimizu 890ddd
	static std::vector<tfxcommand::link> outputLinks(TXsheet *xsh, TFx *fx);</tfxcommand::link>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getHistoryType() { return HistoryType::Schematic; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	static TXshZeraryFxColumn *createZeraryFxColumn(TXsheet *xsh, TFx *zfx, int row = 0);
Toshihiro Shimizu 890ddd
	static void cloneGroupStack(const QStack<int> &groupIds, const QStack<wstring> &groupNames, TFx *toFx);</wstring></int>
Toshihiro Shimizu 890ddd
	static void cloneGroupStack(TFx *fromFx, TFx *toFx);
Toshihiro Shimizu 890ddd
	static void copyGroupEditLevel(int editGroupId, TFx *toFx);
Toshihiro Shimizu 890ddd
	static void copyGroupEditLevel(TFx *fromFx, TFx *toFx);
Toshihiro Shimizu 890ddd
	static void copyDagPosition(TFx *fromFx, TFx *toFx);
Toshihiro Shimizu 890ddd
	static void attach(TXsheet *xsh, TFx *inputFx, TFx *outputFx, int port, bool copyGroupData);
Toshihiro Shimizu 890ddd
	static void attach(TXsheet *xsh, const TFxCommand::Link &link, bool copyGroupData);
Toshihiro Shimizu 890ddd
	static void attachOutputs(TXsheet *xsh, TFx *insertedFx, TFx *inputFx);
Toshihiro Shimizu 890ddd
	static void detachFxs(TXsheet *xsh, TFx *fxLeft, TFx *fxRight, bool detachLeft = true);
Toshihiro Shimizu 890ddd
	static void insertFxs(TXsheet *xsh, const TFxCommand::Link &link, TFx *fxLeft, TFx *fxRight);
Toshihiro Shimizu 890ddd
	static void insertColumn(TXsheet *xsh, TXshColumn *column, int colIdx,
Toshihiro Shimizu 890ddd
							 bool removeHole = false, bool autoTerminal = false);
Toshihiro Shimizu 890ddd
	static void removeFxOrColumn(TXsheet *xsh, TFx *fx, int colIdx,
Toshihiro Shimizu 890ddd
								 bool insertHole = false, bool unlinkParams = true);
Toshihiro Shimizu 890ddd
	static void linkParams(TFx *fx, TFx *linkedFx);
Toshihiro Shimizu 890ddd
	static void unlinkParams(TFx *fx);
Toshihiro Shimizu 890ddd
	static void makeNotCurrent(TFxHandle *fxHandle, TFx *fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	static void removeColumn(TXsheet *xsh, int colIdx, bool insertHole);
Toshihiro Shimizu 890ddd
	static void removeNormalFx(TXsheet *xsh, TFx *fx);
Toshihiro Shimizu 890ddd
	static void removeOutputFx(TXsheet *xsh, TOutputFx *outputFx);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TXshZeraryFxColumn *FxCommandUndo::createZeraryFxColumn(TXsheet *xsh, TFx *zfx, int row)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int frameCount = xsh->getScene()->getFrameCount() - row;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshZeraryFxColumn *column = new TXshZeraryFxColumn(frameCount > 0 ? frameCount : 100);
Toshihiro Shimizu 890ddd
	column->getZeraryColumnFx()->setZeraryFx(zfx);
Toshihiro Shimizu 890ddd
	column->insertEmptyCells(0, row);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return column;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::cloneGroupStack(
Toshihiro Shimizu 890ddd
	const QStack<int> &groupIds, const QStack<wstring> &groupNames, TFx *toFx)</wstring></int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	toFx->getAttributes()->removeFromAllGroup();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 0; i < groupIds.size(); ++i) {
Toshihiro Shimizu 890ddd
		toFx->getAttributes()->setGroupId(groupIds[i]);
Toshihiro Shimizu 890ddd
		toFx->getAttributes()->setGroupName(groupNames[i]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::cloneGroupStack(TFx *fromFx, TFx *toFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fromFx->getAttributes()->isGrouped()) {
Toshihiro Shimizu 890ddd
		cloneGroupStack(fromFx->getAttributes()->getGroupIdStack(),
Toshihiro Shimizu 890ddd
						fromFx->getAttributes()->getGroupNameStack(), toFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::copyGroupEditLevel(int editGroupId, TFx *toFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	toFx->getAttributes()->closeAllGroups();
Toshihiro Shimizu 890ddd
	while (editGroupId != toFx->getAttributes()->getEditingGroupId() &&
Toshihiro Shimizu 890ddd
		   toFx->getAttributes()->editGroup())
Toshihiro Shimizu 890ddd
		;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(editGroupId == toFx->getAttributes()->getEditingGroupId());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::copyGroupEditLevel(TFx *fromFx, TFx *toFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(toFx);
Toshihiro Shimizu 890ddd
	if (fromFx && fromFx->getAttributes()->isGrouped())
Toshihiro Shimizu 890ddd
		copyGroupEditLevel(fromFx->getAttributes()->getEditingGroupId(), toFx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::copyDagPosition(TFx *fromFx, TFx *toFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(toFx);
Toshihiro Shimizu 890ddd
	if (fromFx)
Toshihiro Shimizu 890ddd
		toFx->getAttributes()->setDagNodePos(fromFx->getAttributes()->getDagNodePos());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::attach(TXsheet *xsh, TFx *inputFx, TFx *outputFx, int link,
Toshihiro Shimizu 890ddd
						   bool copyGroupData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (outputFx) {
Toshihiro Shimizu 890ddd
		FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		inputFx = ::getActualOut(inputFx);
Toshihiro Shimizu 890ddd
		outputFx = ::getActualIn(outputFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (inputFx && link < 0) {
Toshihiro Shimizu 890ddd
			assert(dynamic_cast<txsheetfx *="">(outputFx));</txsheetfx>
Toshihiro Shimizu 890ddd
			fxDag->addToXsheet(inputFx);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			int ipCount = outputFx->getInputPortCount();
Toshihiro Shimizu 890ddd
			if (ipCount > 0 && link < ipCount)
Toshihiro Shimizu 890ddd
				outputFx->getInputPort(link)->setFx(inputFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (copyGroupData)
Toshihiro Shimizu 890ddd
				copyGroupEditLevel(inputFx, outputFx);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::attach(TXsheet *xsh, const TFxCommand::Link &link, bool copyGroupData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	attach(xsh, link.m_inputFx.getPointer(), link.m_outputFx.getPointer(), link.m_index, copyGroupData);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::attachOutputs(TXsheet *xsh, TFx *insertedFx, TFx *inputFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TCG_ASSERT(inputFx, return );
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	insertedFx = ::getActualOut(insertedFx);
Toshihiro Shimizu 890ddd
	inputFx = ::getActualOut(inputFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int p, pCount = inputFx->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
	for (p = pCount - 1; p >= 0; --p)					 // Backward iteration on output connections -
Toshihiro Shimizu 890ddd
	{													 // it's necessary since TFxPort::setFx() REMOVES
Toshihiro Shimizu 890ddd
		TFxPort *port = inputFx->getOutputConnection(p); // the corresponding port int the output connections
Toshihiro Shimizu 890ddd
		port->setFx(insertedFx);						 // container - thus, it's better to start from the end
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fxDag->getTerminalFxs()->containsFx(inputFx)) {
Toshihiro Shimizu 890ddd
		fxDag->removeFromXsheet(inputFx);
Toshihiro Shimizu 890ddd
		fxDag->addToXsheet(insertedFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::detachFxs(TXsheet *xsh, TFx *fxLeft, TFx *fxRight, bool detachLeft)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(fxLeft && fxRight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fxLeft = ::getActualIn(fxLeft);
Toshihiro Shimizu 890ddd
	fxRight = ::getActualOut(fxRight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int ipCount = fxLeft->getInputPortCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Redirect input/output ports
Toshihiro Shimizu 890ddd
	TFx *inputFx0 = (ipCount > 0) ? fxLeft->getInputPort(0)->getFx() : 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int p, opCount = fxRight->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
	for (p = opCount - 1; p >= 0; --p) // Backward iteration due to TFxPort::setFx()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TFxPort *outPort = fxRight->getOutputConnection(p);
Toshihiro Shimizu 890ddd
		assert(outPort && outPort->getFx() == fxRight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		outPort->setFx(inputFx0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Xsheet links redirection
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
	if (fxDag->getTerminalFxs()->containsFx(fxRight)) {
Toshihiro Shimizu 890ddd
		fxDag->removeFromXsheet(fxRight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int p = 0; p != ipCount; ++p)
Toshihiro Shimizu 890ddd
			if (TFx *inputFx = fxLeft->getInputPort(p)->getFx())
Toshihiro Shimizu 890ddd
				fxDag->addToXsheet(inputFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (detachLeft)
Toshihiro Shimizu 890ddd
		fxLeft->disconnectAll();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::insertFxs(TXsheet *xsh, const TFxCommand::Link &link,
Toshihiro Shimizu 890ddd
							  TFx *fxLeft, TFx *fxRight)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(fxLeft && fxRight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (link.m_inputFx && link.m_outputFx) {
Toshihiro Shimizu 890ddd
		FxCommandUndo::attach(xsh, link.m_inputFx.getPointer(), fxLeft, 0, false);
Toshihiro Shimizu 890ddd
		FxCommandUndo::attach(xsh, fxRight, link.m_outputFx.getPointer(), link.m_index, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (link.m_index < 0)
Toshihiro Shimizu 890ddd
			xsh->getFxDag()->removeFromXsheet(::getActualOut(link.m_inputFx.getPointer()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::insertColumn(TXsheet *xsh, TXshColumn *column, int col,
Toshihiro Shimizu 890ddd
								 bool removeHole, bool autoTerminal)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
	TFx *fx = column->getFx();
Toshihiro Shimizu 890ddd
	bool terminal = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fx) {
Toshihiro Shimizu 890ddd
		::showFx(xsh, fx);
Toshihiro Shimizu 890ddd
		terminal = fxDag->getTerminalFxs()->containsFx(fx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (removeHole)
Toshihiro Shimizu 890ddd
		xsh->removeColumn(col);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	xsh->insertColumn(col, column); // Attaches the fx to the xsheet, too -
Toshihiro Shimizu 890ddd
									// but not if the column is a palette one.
Toshihiro Shimizu 890ddd
	if (!autoTerminal) {
Toshihiro Shimizu 890ddd
		// Preserve the initial terminal state.
Toshihiro Shimizu 890ddd
		// This lets fxs to be linked to the xsheet while still hidden.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fxDag->removeFromXsheet(fx);
Toshihiro Shimizu 890ddd
		if (terminal)
Toshihiro Shimizu 890ddd
			fxDag->addToXsheet(fx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	xsh->updateFrameCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::removeColumn(TXsheet *xsh, int col, bool insertHole)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TFx *colFx = xsh->getColumn(col)->getFx()) {
Toshihiro Shimizu 890ddd
		detachFxs(xsh, colFx, colFx);
Toshihiro Shimizu 890ddd
		::hideFx(xsh, colFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	xsh->removeColumn(col);		// Already detaches any fx in output,
Toshihiro Shimizu 890ddd
	if (insertHole)				// including the terminal case
Toshihiro Shimizu 890ddd
		xsh->insertColumn(col); // Note that fxs in output are not
Toshihiro Shimizu 890ddd
								// removed - just detached.
Toshihiro Shimizu 890ddd
	xsh->updateFrameCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::removeNormalFx(TXsheet *xsh, TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	detachFxs(xsh, fx, fx);
Toshihiro Shimizu 890ddd
	::removeFxFromCurrentScene(fx, xsh); // Already hideFx()s
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::removeOutputFx(TXsheet *xsh, TOutputFx *outputFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	detachFxs(xsh, outputFx, outputFx);
Toshihiro Shimizu 890ddd
	xsh->getFxDag()->removeOutputFx(outputFx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::linkParams(TFx *fx, TFx *linkedFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (linkedFx)
Toshihiro Shimizu 890ddd
		::getActualIn(fx)->linkParams(::getActualIn(linkedFx));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::unlinkParams(TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fx = ::getActualIn(fx), fx->getLinkedFx())
Toshihiro Shimizu 890ddd
		fx->unlinkParams();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::makeNotCurrent(TFxHandle *fxHandle, TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fx = ::getActualOut(fx), fx == fxHandle->getFx())
Toshihiro Shimizu 890ddd
		fxHandle->setFx(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxCommandUndo::removeFxOrColumn(TXsheet *xsh, TFx *fx, int colIdx,
Toshihiro Shimizu 890ddd
									 bool insertHole, bool unlinkParams)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(fx || colIdx >= 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!fx)
Toshihiro Shimizu 890ddd
		fx = xsh->getColumn(colIdx)->getFx();
Toshihiro Shimizu 890ddd
	else if (TColumnFx *colFx = dynamic_cast<tcolumnfx *="">(fx))</tcolumnfx>
Toshihiro Shimizu 890ddd
		colIdx = colFx->getColumnIndex();
Toshihiro Shimizu 890ddd
	else if (TZeraryFx *zfx = dynamic_cast<tzeraryfx *="">(fx)) {</tzeraryfx>
Toshihiro Shimizu 890ddd
		if (zfx->getColumnFx())
Toshihiro Shimizu 890ddd
			fx = zfx->getColumnFx(), colIdx = static_cast<tcolumnfx *="">(fx)->getColumnIndex();</tcolumnfx>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fx) {
Toshihiro Shimizu 890ddd
		// Discriminate special fx types
Toshihiro Shimizu 890ddd
		if (TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(fx)) {</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
			// Removed as a column
Toshihiro Shimizu 890ddd
			fx = zcfx->getZeraryFx();
Toshihiro Shimizu 890ddd
		} else if (TOutputFx *outputFx = dynamic_cast<toutputfx *="">(fx)) {</toutputfx>
Toshihiro Shimizu 890ddd
			assert(xsh->getFxDag()->getOutputFxCount() > 1);
Toshihiro Shimizu 890ddd
			FxCommandUndo::removeOutputFx(xsh, outputFx);
Toshihiro Shimizu 890ddd
		} else if (colIdx < 0)
Toshihiro Shimizu 890ddd
			FxCommandUndo::removeNormalFx(xsh, fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (unlinkParams)
Toshihiro Shimizu 890ddd
			FxCommandUndo::unlinkParams(fx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (colIdx >= 0)
Toshihiro Shimizu 890ddd
		FxCommandUndo::removeColumn(xsh, colIdx, insertHole);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pred=""></typename>
Toshihiro Shimizu 890ddd
TFx *FxCommandUndo::leftmostConnectedFx(TFx *fx, Pred pred)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fx = rightmostConnectedFx(fx, pred); // The rightmost fx should be discovered first,
Toshihiro Shimizu 890ddd
										 // then, we'll descend from that
Toshihiro Shimizu 890ddd
	do {
Toshihiro Shimizu 890ddd
		fx = ::getActualIn(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!((fx->getInputPortCount() > 0) &&
Toshihiro Shimizu 890ddd
			  fx->getInputPort(0)->isConnected() &&
Toshihiro Shimizu 890ddd
			  pred(fx->getInputPort(0)->getFx())))
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fx = fx->getInputPort(0)->getFx();
Toshihiro Shimizu 890ddd
	} while (true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return fx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pred=""></typename>
Toshihiro Shimizu 890ddd
TFx *FxCommandUndo::rightmostConnectedFx(TFx *fx, Pred pred)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	do {
Toshihiro Shimizu 890ddd
		fx = ::getActualOut(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!(fx->getOutputConnectionCount() > 0 &&
Toshihiro Shimizu 890ddd
			  pred(fx->getOutputConnection(0)->getOwnerFx())))
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fx = fx->getOutputConnection(0)->getOwnerFx();
Toshihiro Shimizu 890ddd
	} while (true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return fx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
struct True_pred {
Toshihiro Shimizu 890ddd
	bool operator()(TFx *fx) { return true; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFx *FxCommandUndo::leftmostConnectedFx(TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return leftmostConnectedFx(fx, ::True_pred());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFx *FxCommandUndo::rightmostConnectedFx(TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return rightmostConnectedFx(fx, ::True_pred());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::vector<tfxcommand::link> FxCommandUndo::inputLinks(TXsheet *xsh, TFx *fx)</tfxcommand::link>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<tfxcommand::link> result;</tfxcommand::link>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fx = ::getActualIn(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int il, ilCount = fx->getInputPortCount();
Toshihiro Shimizu 890ddd
	for (il = 0; il != ilCount; ++il) {
Toshihiro Shimizu 890ddd
		TFxPort *port = fx->getInputPort(il);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(port);
Toshihiro Shimizu 890ddd
		if (port->isConnected())
Toshihiro Shimizu 890ddd
			result.push_back(TFxCommand::Link(port->getFx(), fx, il));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::vector<tfxcommand::link> FxCommandUndo::outputLinks(TXsheet *xsh, TFx *fx)</tfxcommand::link>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<tfxcommand::link> result;</tfxcommand::link>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fx = ::getActualOut(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int ol, olCount = fx->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
	for (ol = 0; ol != olCount; ++ol) {
Toshihiro Shimizu 890ddd
		TFxPort *port = fx->getOutputConnection(ol);
Toshihiro Shimizu 890ddd
		TFx *ownerFx = port->getOwnerFx();
Toshihiro Shimizu 890ddd
		int portIndex = ::inputPortIndex(ownerFx, port);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		result.push_back(TFxCommand::Link(fx, ownerFx, portIndex));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
	if (fxDag->getTerminalFxs()->containsFx(fx))
Toshihiro Shimizu 890ddd
		result.push_back(TFxCommand::Link(fx, fxDag->getXsheetFx(), -1));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Insert Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class InsertFxUndo : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QList<tfxp> m_selectedFxs;</tfxp>
Toshihiro Shimizu 890ddd
	QList<tfxcommand::link> m_selectedLinks;</tfxcommand::link>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TApplication *m_app;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QList<tfxp> m_insertedFxs;</tfxp>
Toshihiro Shimizu 890ddd
	TXshZeraryFxColumnP m_insertedColumn;
Toshihiro Shimizu 890ddd
	int m_colIdx;
Toshihiro Shimizu 890ddd
	bool m_columnReplacesHole;
Toshihiro Shimizu 890ddd
	bool m_attachOutputs;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	InsertFxUndo(const TFxP &fx, int row, int col,
Toshihiro Shimizu 890ddd
				 const QList<tfxp> &selectedFxs, QList<tfxcommand::link> selectedLinks,</tfxcommand::link></tfxp>
Toshihiro Shimizu 890ddd
				 TApplication *app, bool attachOutputs = true)
Toshihiro Shimizu 890ddd
		: m_selectedFxs(selectedFxs), m_selectedLinks(selectedLinks), m_insertedColumn(0), m_app(app), m_colIdx(col), m_columnReplacesHole(false), m_attachOutputs(attachOutputs)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize(fx, row, col);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return !m_insertedFxs.isEmpty(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize(const TFxP &newFx, int row, int col);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline bool has_fx_column(TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TPluginInterface *plgif = dynamic_cast<tplugininterface *="">(fx))</tplugininterface>
Toshihiro Shimizu 890ddd
		return plgif->isPluginZerary();
Toshihiro Shimizu 890ddd
	else if (TZeraryFx *zfx = dynamic_cast<tzeraryfx *="">(fx))</tzeraryfx>
Toshihiro Shimizu 890ddd
		return zfx->isZerary();
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool containsInputFx(const QList<tfxp> &fxs, const TFxCommand::Link &link)</tfxp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return fxs.contains(link.m_inputFx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
typedef tcg::function<bool (*)(const="" qlist<tfxp=""> &, const TFxCommand::Link &), containsInputFx> ContainsInputFx_fun;</bool>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void InsertFxUndo::initialize(const TFxP &newFx, int row, int col)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct Locals {
Toshihiro Shimizu 890ddd
		InsertFxUndo *m_this;
Toshihiro Shimizu 890ddd
		inline void storeFx(TXsheet *xsh, TFx *fx)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			::initializeFx(xsh, fx);
Toshihiro Shimizu 890ddd
			m_this->m_insertedFxs.push_back(fx);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} locals = {this};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
	TFx *fx = newFx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(!dynamic_cast<tzerarycolumnfx *="">(fx));</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TZeraryFx *zfx = dynamic_cast<tzeraryfx *="">(fx);</tzeraryfx>
Toshihiro Shimizu 890ddd
	if (has_fx_column(fx)) {
Toshihiro Shimizu 890ddd
		m_insertedColumn = InsertFxUndo::createZeraryFxColumn(xsh, fx, row);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		locals.storeFx(xsh, fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (xsh->getColumn(col) && xsh->getColumn(col)->isEmpty())
Toshihiro Shimizu 890ddd
			m_columnReplacesHole = true;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		if (m_selectedFxs.isEmpty() && m_selectedLinks.isEmpty()) {
Toshihiro Shimizu 890ddd
			// Attempt retrieval of current Fx from the fxHandle
Toshihiro Shimizu 890ddd
			if (TFx *currentFx = m_app->getCurrentFx()->getFx())
Toshihiro Shimizu 890ddd
				m_selectedFxs.push_back(currentFx);
Toshihiro Shimizu 890ddd
			else {
Toshihiro Shimizu 890ddd
				// Isolated case
Toshihiro Shimizu 890ddd
				locals.storeFx(xsh, fx);
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Remove all unacceptable input fxs
Toshihiro Shimizu 890ddd
		::FilterInsideAMacro filterInMacroFxs = {xsh};
Toshihiro Shimizu 890ddd
		m_selectedFxs.erase(std::remove_if(m_selectedFxs.begin(), m_selectedFxs.end(), filterInMacroFxs),
Toshihiro Shimizu 890ddd
							m_selectedFxs.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Remove all unacceptable links or links whose input fx was already selected
Toshihiro Shimizu 890ddd
		m_selectedLinks.erase(std::remove_if(m_selectedLinks.begin(), m_selectedLinks.end(), filterInMacroFxs),
Toshihiro Shimizu 890ddd
							  m_selectedLinks.end());
Toshihiro Shimizu 890ddd
		m_selectedLinks.erase(std::remove_if(m_selectedLinks.begin(), m_selectedLinks.end(),
Toshihiro Shimizu 890ddd
											 tcg::bind1st(::ContainsInputFx_fun(), m_selectedFxs)),
Toshihiro Shimizu 890ddd
							  m_selectedLinks.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Build an fx for each of the specified inputs
Toshihiro Shimizu 890ddd
		::CloneFxFunctor cloneFx = {fx, true};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int f, fCount = m_selectedFxs.size();
Toshihiro Shimizu 890ddd
		for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
			TFx *fx = cloneFx();
Toshihiro Shimizu 890ddd
			FxCommandUndo::cloneGroupStack(m_selectedFxs[f].getPointer(), fx);
Toshihiro Shimizu 890ddd
			locals.storeFx(xsh, fx);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fCount = m_selectedLinks.size();
Toshihiro Shimizu 890ddd
		for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
			TFx *fx = cloneFx();
Toshihiro Shimizu 890ddd
			FxCommandUndo::cloneGroupStack(m_selectedLinks[f].m_inputFx.getPointer(), fx);
Toshihiro Shimizu 890ddd
			locals.storeFx(xsh, fx);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void InsertFxUndo::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct OnExit {
Toshihiro Shimizu 890ddd
		const InsertFxUndo *m_this;
Toshihiro Shimizu 890ddd
		~OnExit()
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			m_this->m_app->getCurrentFx()->setFx(m_this->m_insertedFxs.back().getPointer());
Toshihiro Shimizu 890ddd
			m_this->m_app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
			m_this->m_app->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} onExit = {this};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Zerary case
Toshihiro Shimizu 890ddd
	if (m_insertedColumn) {
Toshihiro Shimizu 890ddd
		FxCommandUndo::insertColumn(
Toshihiro Shimizu 890ddd
			xsh, m_insertedColumn.getPointer(), m_colIdx, m_columnReplacesHole, true);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Isolated Fx case
Toshihiro Shimizu 890ddd
	if (m_selectedLinks.isEmpty() && m_selectedFxs.isEmpty()) {
Toshihiro Shimizu 890ddd
		assert(m_insertedFxs.size() == 1);
Toshihiro Shimizu 890ddd
		::addFxToCurrentScene(m_insertedFxs.back().getPointer(), xsh, false); // Already showFx()s
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		// Selected links
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < m_selectedLinks.size(); ++i) {
Toshihiro Shimizu 890ddd
			const TFxCommand::Link &link = m_selectedLinks[i];
Toshihiro Shimizu 890ddd
			TFx *insertedFx = m_insertedFxs[i].getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			::addFxToCurrentScene(insertedFx, xsh, false);
Toshihiro Shimizu 890ddd
			FxCommandUndo::insertFxs(xsh, link, insertedFx, insertedFx);
Toshihiro Shimizu 890ddd
			FxCommandUndo::copyGroupEditLevel(link.m_inputFx.getPointer(), insertedFx);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Selected fxs
Toshihiro Shimizu 890ddd
		int j, t;
Toshihiro Shimizu 890ddd
		for (j = 0, t = 0; j < m_selectedFxs.size(); j++) {
Toshihiro Shimizu 890ddd
			TFx *fx = m_selectedFxs[j].getPointer();
Toshihiro Shimizu 890ddd
			assert(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TFx *insertedFx = m_insertedFxs[i + t].getPointer();
Toshihiro Shimizu 890ddd
			t++;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			assert(insertedFx);
Toshihiro Shimizu 890ddd
			::addFxToCurrentScene(insertedFx, xsh, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (m_attachOutputs)
Toshihiro Shimizu 890ddd
				FxCommandUndo::attachOutputs(xsh, insertedFx, fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			FxCommandUndo::attach(xsh, fx, insertedFx, 0, true);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void InsertFxUndo::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, iCount = m_insertedFxs.size();
Toshihiro Shimizu 890ddd
	for (i = 0; i != iCount; ++i) {
Toshihiro Shimizu 890ddd
		TFx *insertedFx = m_insertedFxs[i].getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		FxCommandUndo::removeFxOrColumn(xsh, insertedFx, -1,
Toshihiro Shimizu 890ddd
										m_columnReplacesHole, false); // Skip parameter links removal
Toshihiro Shimizu 890ddd
		FxCommandUndo::makeNotCurrent(m_app->getCurrentFx(), insertedFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_app->getCurrentFx()->setFx(0);
Toshihiro Shimizu 890ddd
	m_app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	m_app->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString InsertFxUndo::getHistoryString()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QString str = (m_selectedLinks.isEmpty()) ? QObject::tr("Add Fx  : ") : QObject::tr("Insert Fx  : ");
Toshihiro Shimizu 890ddd
	QList<tfxp>::iterator it;</tfxp>
Toshihiro Shimizu 890ddd
	for (it = m_insertedFxs.begin(); it != m_insertedFxs.end(); it++) {
Toshihiro Shimizu 890ddd
		if (it != m_insertedFxs.begin())
Toshihiro Shimizu 890ddd
			str += QString(", ");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		str += QString::fromStdWString((*it)->getFxId());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return str;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::insertFx(TFx *newFx, const QList<tfxp> &fxs, const QList<link> &links,</tfxp>
Toshihiro Shimizu 890ddd
						  TApplication *app, int col, int row)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!newFx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new InsertFxUndo(newFx, row, col, fxs, links, app));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Add Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::addFx(TFx *newFx, const QList<tfxp> &fxs, TApplication *app, int col, int row)</tfxp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!newFx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new InsertFxUndo(newFx, row, col, fxs, QList<link>(), app, false));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (!undo->isConsistent())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	undo->redo();
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Duplicate Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class DuplicateFxUndo : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFxP m_fx, m_dupFx;
Toshihiro Shimizu 890ddd
	TXshColumnP m_column;
Toshihiro Shimizu 890ddd
	int m_colIdx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
	TFxHandle *m_fxHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	DuplicateFxUndo(const TFxP &originalFx, TXsheetHandle *xshHandle, TFxHandle *fxHandle)
Toshihiro Shimizu 890ddd
		: m_fx(originalFx), m_colIdx(-1), m_xshHandle(xshHandle), m_fxHandle(fxHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return bool(m_dupFx); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DuplicateFxUndo::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	TFx *fx = m_fx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fx = ::getActualOut(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isInsideAMacroFx(fx, xsh) ||
Toshihiro Shimizu 890ddd
		dynamic_cast<txsheetfx *="">(fx) || dynamic_cast<toutputfx *="">(fx) ||</toutputfx></txsheetfx>
Toshihiro Shimizu 890ddd
		(dynamic_cast<tcolumnfx *="">(fx) && !dynamic_cast<tzerarycolumnfx *="">(fx)))</tzerarycolumnfx></tcolumnfx>
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(fx)) {</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		m_column = new TXshZeraryFxColumn(*zcfx->getColumn());
Toshihiro Shimizu 890ddd
		m_colIdx = xsh->getFirstFreeColumnIndex();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TZeraryColumnFx *dupZcfx = static_cast<tzerarycolumnfx *="">(m_column->getFx());</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		::initializeFx(xsh, dupZcfx->getZeraryFx());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		FxCommandUndo::cloneGroupStack(zcfx, dupZcfx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_dupFx = dupZcfx;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		fx = fx->clone(false);
Toshihiro Shimizu 890ddd
		::initializeFx(xsh, fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		FxCommandUndo::cloneGroupStack(m_fx.getPointer(), fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_dupFx = fx;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DuplicateFxUndo::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_column) {
Toshihiro Shimizu 890ddd
		// Zerary Fx case
Toshihiro Shimizu 890ddd
		TZeraryColumnFx *zcfx = static_cast<tzerarycolumnfx *="">(m_fx.getPointer());</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		TZeraryColumnFx *dupZcfx = static_cast<tzerarycolumnfx *="">(m_dupFx.getPointer());</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		FxCommandUndo::insertColumn(xsh, m_column.getPointer(), m_colIdx, true, true);
Toshihiro Shimizu 890ddd
		FxCommandUndo::copyGroupEditLevel(zcfx, dupZcfx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		dupZcfx->getZeraryFx()->linkParams(zcfx->getZeraryFx());
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		// Normal Fx case
Toshihiro Shimizu 890ddd
		addFxToCurrentScene(m_dupFx.getPointer(), m_xshHandle->getXsheet(), false);
Toshihiro Shimizu 890ddd
		FxCommandUndo::copyGroupEditLevel(m_fx.getPointer(), m_dupFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_dupFx->linkParams(m_fx.getPointer());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_fxHandle->setFx(m_dupFx.getPointer());
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DuplicateFxUndo::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FxCommandUndo::removeFxOrColumn(
Toshihiro Shimizu 890ddd
		m_xshHandle->getXsheet(), m_dupFx.getPointer(), -1, true, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_fxHandle->setFx(0);
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString DuplicateFxUndo::getHistoryString()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TZeraryColumnFx *zDup = dynamic_cast<tzerarycolumnfx *="">(m_dupFx.getPointer()))</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		return QObject::tr("Create Linked Fx  : %1")
Toshihiro Shimizu 890ddd
			.arg(QString::fromStdWString(zDup->getZeraryFx()->getFxId()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return QObject::tr("Create Linked Fx  : %1")
Toshihiro Shimizu 890ddd
		.arg(QString::fromStdWString(m_dupFx->getFxId()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::duplicateFx(TFx *src, TXsheetHandle *xshHandle, TFxHandle *fxHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new DuplicateFxUndo(src, xshHandle, fxHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Replace Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ReplaceFxUndo : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFxP m_fx, m_repFx, m_linkedFx;
Toshihiro Shimizu 890ddd
	TXshColumnP m_column, m_repColumn;
Toshihiro Shimizu 890ddd
	int m_colIdx, m_repColIdx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<std::pair<int, *="" tfx="">> m_inputLinks;</std::pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
	TFxHandle *m_fxHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ReplaceFxUndo(const TFxP &replacementFx, const TFxP &replacedFx,
Toshihiro Shimizu 890ddd
				  TXsheetHandle *xshHandle, TFxHandle *fxHandle)
Toshihiro Shimizu 890ddd
		: m_fx(replacedFx), m_repFx(replacementFx), m_xshHandle(xshHandle), m_fxHandle(fxHandle), m_colIdx(-1), m_repColIdx(-1)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return bool(m_repFx); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
	static void replace(TXsheet *xsh, TFx *fx, TFx *repFx,
Toshihiro Shimizu 890ddd
						TXshColumn *column, TXshColumn *repColumn,
Toshihiro Shimizu 890ddd
						int colIdx, int repColIdx);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ReplaceFxUndo::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFx *fx = m_fx.getPointer();
Toshihiro Shimizu 890ddd
	TFx *repFx = m_repFx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fx = ::getActualOut(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isInsideAMacroFx(fx, xsh) ||
Toshihiro Shimizu 890ddd
		dynamic_cast<txsheetfx *="">(fx) || dynamic_cast<toutputfx *="">(fx) ||</toutputfx></txsheetfx>
Toshihiro Shimizu 890ddd
		(dynamic_cast<tcolumnfx *="">(fx) && !dynamic_cast<tzerarycolumnfx *="">(fx))) {</tzerarycolumnfx></tcolumnfx>
Toshihiro Shimizu 890ddd
		m_repFx = TFxP();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (dynamic_cast<txsheetfx *="">(repFx) || dynamic_cast<toutputfx *="">(repFx) ||</toutputfx></txsheetfx>
Toshihiro Shimizu 890ddd
		dynamic_cast<tcolumnfx *="">(repFx)) {</tcolumnfx>
Toshihiro Shimizu 890ddd
		m_repFx = TFxP();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	::initializeFx(xsh, repFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(fx);</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
	if (zcfx) {
Toshihiro Shimizu 890ddd
		TXshZeraryFxColumn *zfColumn = zcfx->getColumn();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_column = zfColumn;
Toshihiro Shimizu 890ddd
		m_colIdx = zfColumn->getIndex();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fx = zcfx->getZeraryFx();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (has_fx_column(fx)) {
Toshihiro Shimizu 890ddd
		if (zcfx) {
Toshihiro Shimizu 890ddd
			// Build a column with the same source cells pattern
Toshihiro Shimizu 890ddd
			m_repColumn = new TXshZeraryFxColumn(*zcfx->getColumn());
Toshihiro Shimizu 890ddd
			m_repColIdx = m_colIdx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Substitute the column's zerary fx with the subsitute one
Toshihiro Shimizu 890ddd
			TZeraryColumnFx *repZcfx = static_cast<tzerarycolumnfx *="">(m_repColumn->getFx());</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
			repZcfx->setZeraryFx(repFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			FxCommandUndo::cloneGroupStack(zcfx, repZcfx);
Toshihiro Shimizu 890ddd
			m_repFx = repZcfx;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			m_repColumn = FxCommandUndo::createZeraryFxColumn(xsh, repFx);
Toshihiro Shimizu 890ddd
			m_repColIdx = xsh->getFirstFreeColumnIndex();
Toshihiro Shimizu 890ddd
			m_repFx = static_cast<tzerarycolumnfx *="">(m_repColumn->getFx());</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FxCommandUndo::cloneGroupStack(fx, m_repFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Store fx's input links (depending on m_repFx, they could be not matched
Toshihiro Shimizu 890ddd
	// in the replacement)
Toshihiro Shimizu 890ddd
	int p, ipCount = fx->getInputPortCount();
Toshihiro Shimizu 890ddd
	for (p = 0; p != ipCount; ++p) {
Toshihiro Shimizu 890ddd
		TFxPort *port = fx->getInputPort(p);
Toshihiro Shimizu 890ddd
		if (TFx *inputFx = port->getFx())
Toshihiro Shimizu 890ddd
			m_inputLinks.push_back(std::make_pair(p, inputFx));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Store the fx's linked fx
Toshihiro Shimizu 890ddd
	m_linkedFx = fx->getLinkedFx();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ReplaceFxUndo::replace(TXsheet *xsh,
Toshihiro Shimizu 890ddd
							TFx *fx, TFx *repFx,
Toshihiro Shimizu 890ddd
							TXshColumn *column, TXshColumn *repColumn,
Toshihiro Shimizu 890ddd
							int colIdx, int repColIdx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TZeraryColumnFx *zcfx = column ? static_cast<tzerarycolumnfx *="">(fx) : 0;</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
	TZeraryColumnFx *repZcfx = repColumn ? static_cast<tzerarycolumnfx *="">(repFx) : 0;</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFx *ifx = zcfx ? zcfx->getZeraryFx() : fx;
Toshihiro Shimizu 890ddd
	TFx *irepFx = repZcfx ? repZcfx->getZeraryFx() : repFx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Copy links first
Toshihiro Shimizu 890ddd
	int p, ipCount = ifx->getInputPortCount(), ripCount = irepFx->getInputPortCount();
Toshihiro Shimizu 890ddd
	for (p = 0; p != ipCount && p != ripCount; ++p) {
Toshihiro Shimizu 890ddd
		TFxPort *ifxPort = ifx->getInputPort(p);
Toshihiro Shimizu 890ddd
		TFxPort *irepFxPort = irepFx->getInputPort(p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		FxCommandUndo::attach(xsh, ifxPort->getFx(), irepFx, p, true);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int opCount = fx->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
	for (p = opCount - 1; p >= 0; --p) {
Toshihiro Shimizu 890ddd
		TFxPort *port = fx->getOutputConnection(p);
Toshihiro Shimizu 890ddd
		port->setFx(repFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fxDag->getTerminalFxs()->containsFx(fx)) {
Toshihiro Shimizu 890ddd
		fxDag->removeFromXsheet(fx);
Toshihiro Shimizu 890ddd
		fxDag->addToXsheet(repFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Remove fx/column
Toshihiro Shimizu 890ddd
	FxCommandUndo::removeFxOrColumn(xsh, fx, colIdx, bool(repColumn), false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Insert the new fx/column
Toshihiro Shimizu 890ddd
	if (repColumn)
Toshihiro Shimizu 890ddd
		FxCommandUndo::insertColumn(xsh, repColumn, repColIdx, column); // Not attached to the xsheet
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		::addFxToCurrentScene(repFx, xsh, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FxCommandUndo::copyGroupEditLevel(fx, repFx);
Toshihiro Shimizu 890ddd
	FxCommandUndo::copyDagPosition(fx, repFx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ReplaceFxUndo::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ReplaceFxUndo::replace(m_xshHandle->getXsheet(),
Toshihiro Shimizu 890ddd
						   m_fx.getPointer(), m_repFx.getPointer(),
Toshihiro Shimizu 890ddd
						   m_column.getPointer(), m_repColumn.getPointer(),
Toshihiro Shimizu 890ddd
						   m_colIdx, m_repColIdx);
Toshihiro Shimizu 890ddd
	FxCommandUndo::unlinkParams(m_fx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_fxHandle->setFx(0);
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ReplaceFxUndo::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ReplaceFxUndo::replace(m_xshHandle->getXsheet(),
Toshihiro Shimizu 890ddd
						   m_repFx.getPointer(), m_fx.getPointer(),
Toshihiro Shimizu 890ddd
						   m_repColumn.getPointer(), m_column.getPointer(),
Toshihiro Shimizu 890ddd
						   m_repColIdx, m_colIdx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Repair original input links for m_fx
Toshihiro Shimizu 890ddd
	m_fx->disconnectAll();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	size_t l, lCount = m_inputLinks.size();
Toshihiro Shimizu 890ddd
	for (l = 0; l != lCount; ++l)
Toshihiro Shimizu 890ddd
		m_fx->getInputPort(m_inputLinks[l].first)->setFx(m_inputLinks[l].second);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Repair parameter links
Toshihiro Shimizu 890ddd
	FxCommandUndo::linkParams(m_fx.getPointer(), m_linkedFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_fxHandle->setFx(0);
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString ReplaceFxUndo::getHistoryString()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QString str = QObject::tr("Replace Fx  : ");
Toshihiro Shimizu 890ddd
	str += QString("%1 > %2")
Toshihiro Shimizu 890ddd
			   .arg(QString::fromStdWString(m_fx->getFxId()))
Toshihiro Shimizu 890ddd
			   .arg(QString::fromStdWString(m_repFx->getFxId()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return str;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::replaceFx(TFx *newFx, const QList<tfxp> &fxs, TXsheetHandle *xshHandle, TFxHandle *fxHandle)</tfxp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!newFx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TUndoManager *undoManager = TUndoManager::manager();
Toshihiro Shimizu 890ddd
	::CloneFxFunctor cloneFx = {newFx, true};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	undoManager->beginBlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFxP clonedFx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int f, fCount = fxs.size();
Toshihiro Shimizu 890ddd
	for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
		if (!clonedFx)
Toshihiro Shimizu 890ddd
			clonedFx = cloneFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::auto_ptr<fxcommandundo> undo(new ReplaceFxUndo(clonedFx, fxs[f], xshHandle, fxHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
		if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
			undo->redo();
Toshihiro Shimizu 890ddd
			undoManager->add(undo.release());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			clonedFx = TFxP();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	undoManager->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Unlink Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UnlinkFxUndo : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFxP m_fx, m_linkedFx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UnlinkFxUndo(const TFxP &fx, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
		: m_fx(fx), m_linkedFx(fx->getLinkedFx()), m_xshHandle(xshHandle) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return bool(m_linkedFx); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void undo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		FxCommandUndo::linkParams(m_fx.getPointer(), m_linkedFx.getPointer());
Toshihiro Shimizu 890ddd
		m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		FxCommandUndo::unlinkParams(m_fx.getPointer());
Toshihiro Shimizu 890ddd
		m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QObject::tr("Unlink Fx  : %1 - - %2")
Toshihiro Shimizu 890ddd
			.arg(QString::fromStdWString(m_fx->getFxId()))
Toshihiro Shimizu 890ddd
			.arg(QString::fromStdWString(m_linkedFx->getFxId()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::unlinkFx(TFx *fx, TFxHandle *fxHandle, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!fx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new UnlinkFxUndo(fx, xshHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Make Macro Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class MakeMacroUndo : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	TFxP m_macroFx;
Toshihiro Shimizu 890ddd
	TApplication *m_app;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	MakeMacroUndo(const std::vector<tfxp> &fxs, TApplication *app)</tfxp>
Toshihiro Shimizu 890ddd
		: m_app(app)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize(fxs);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return bool(m_macroFx); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	virtual QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QObject::tr("Make Macro Fx  : %1")
Toshihiro Shimizu 890ddd
			.arg(QString::fromStdWString(m_macroFx->getFxId()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize(const std::vector<tfxp> &fxs);</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	MakeMacroUndo(TMacroFx *macroFx, TApplication *app)
Toshihiro Shimizu 890ddd
		: m_macroFx(macroFx), m_app(app) {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MakeMacroUndo::initialize(const std::vector<tfxp> &fxs)</tfxp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	size_t f, fCount = fxs.size();
Toshihiro Shimizu 890ddd
	for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
		// Only normal Fxs can be added in a macro
Toshihiro Shimizu 890ddd
		TFx *fx = fxs[f].getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (isInsideAMacroFx(fx, xsh) ||
Toshihiro Shimizu 890ddd
			fx->isZerary() ||
Toshihiro Shimizu 890ddd
			dynamic_cast<tzerarycolumnfx *="">(fx) ||</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
			dynamic_cast<tmacrofx *="">(fx) ||</tmacrofx>
Toshihiro Shimizu 890ddd
			dynamic_cast<tlevelcolumnfx *="">(fx) ||</tlevelcolumnfx>
Toshihiro Shimizu 890ddd
			dynamic_cast<tpalettecolumnfx *="">(fx) ||</tpalettecolumnfx>
Toshihiro Shimizu 890ddd
			dynamic_cast<txsheetfx *="">(fx) ||</txsheetfx>
Toshihiro Shimizu 890ddd
			dynamic_cast<toutputfx *="">(fx))</toutputfx>
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TMacroFx *macroFx = TMacroFx::create(fxs);
Toshihiro Shimizu 890ddd
	if (!macroFx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	::initializeFx(xsh, macroFx);
Toshihiro Shimizu 890ddd
	m_macroFx = TFxP(macroFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// An old comment suggested there may be trouble in case the fx editor popup is opened.
Toshihiro Shimizu 890ddd
	// In any case, the new macro fx will be selected at the end - so, let's disable it right now
Toshihiro Shimizu 890ddd
	m_app->getCurrentFx()->setFx(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MakeMacroUndo::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
	TFxSet *terminalFxs = fxDag->getTerminalFxs();
Toshihiro Shimizu 890ddd
	TMacroFx *macroFx = static_cast<tmacrofx *="">(m_macroFx.getPointer());</tmacrofx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	::addFxToCurrentScene(macroFx, xsh, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Replace the macro's root and deal with output links
Toshihiro Shimizu 890ddd
	TFx *rootFx = macroFx->getRoot();
Toshihiro Shimizu 890ddd
	if (terminalFxs->containsFx(rootFx))
Toshihiro Shimizu 890ddd
		fxDag->addToXsheet(macroFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int p, opCount = rootFx->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
	for (p = opCount - 1; p >= 0; --p)
Toshihiro Shimizu 890ddd
		rootFx->getOutputConnection(p)->setFx(macroFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Remove the macro's internal fxs from the scene
Toshihiro Shimizu 890ddd
	const vector<tfxp> &fxs = macroFx->getFxs();</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	size_t f, fCount = fxs.size();
Toshihiro Shimizu 890ddd
	for (f = 0; f != fCount; ++f)
Toshihiro Shimizu 890ddd
		::removeFxFromCurrentScene(fxs[f].getPointer(), xsh);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Hijack their ports (no actual redirection) - resetting the port ownership.
Toshihiro Shimizu 890ddd
	// NOTE: Is this even legal? Not gonna touch it, but...   o_o!
Toshihiro Shimizu 890ddd
	int ipCount = macroFx->getInputPortCount();
Toshihiro Shimizu 890ddd
	for (p = 0; p != ipCount; ++p)
Toshihiro Shimizu 890ddd
		macroFx->getInputPort(p)->setOwnerFx(macroFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_app->getCurrentFx()->setFx(macroFx);
Toshihiro Shimizu 890ddd
	m_app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MakeMacroUndo::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
	TFxSet *terminalFxs = fxDag->getTerminalFxs();
Toshihiro Shimizu 890ddd
	TMacroFx *macroFx = static_cast<tmacrofx *="">(m_macroFx.getPointer());</tmacrofx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Reattach the macro's root to the xsheet if necessary
Toshihiro Shimizu 890ddd
	TFx *rootFx = macroFx->getRoot();
Toshihiro Shimizu 890ddd
	if (terminalFxs->containsFx(macroFx))
Toshihiro Shimizu 890ddd
		fxDag->addToXsheet(rootFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Restore the root's output connections
Toshihiro Shimizu 890ddd
	int p, opCount = macroFx->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
	for (p = opCount - 1; p >= 0; --p)
Toshihiro Shimizu 890ddd
		macroFx->getOutputConnection(p)->setFx(rootFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Remove the macro
Toshihiro Shimizu 890ddd
	::removeFxFromCurrentScene(macroFx, xsh);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Re-insert the macro's internal fxs and restore ports ownership
Toshihiro Shimizu 890ddd
	const vector<tfxp> &fxs = macroFx->getFxs();</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	size_t f, fCount = fxs.size();
Toshihiro Shimizu 890ddd
	for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
		TFx *fx = fxs[f].getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		::addFxToCurrentScene(fx, xsh, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int p, ipCount = fx->getInputPortCount();
Toshihiro Shimizu 890ddd
		for (p = 0; p != ipCount; ++p)
Toshihiro Shimizu 890ddd
			fx->getInputPort(p)->setOwnerFx(fx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_app->getCurrentFx()->setFx(0);
Toshihiro Shimizu 890ddd
	m_app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::makeMacroFx(const std::vector<tfxp> &fxs, TApplication *app)</tfxp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fxs.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new MakeMacroUndo(fxs, app));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Explode Macro Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ExplodeMacroUndo : public MakeMacroUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ExplodeMacroUndo(TMacroFx *macro, TApplication *app)
Toshihiro Shimizu 890ddd
		: MakeMacroUndo(macro, app)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const { MakeMacroUndo::undo(); }
Toshihiro Shimizu 890ddd
	void undo() const { MakeMacroUndo::redo(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QObject::tr("Explode Macro Fx  : %1")
Toshihiro Shimizu 890ddd
			.arg(QString::fromStdWString(m_macroFx->getFxId()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ExplodeMacroUndo::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!static_cast<tmacrofx *="">(m_macroFx.getPointer())->getRoot())</tmacrofx>
Toshihiro Shimizu 890ddd
		m_macroFx = TFxP();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::explodeMacroFx(TMacroFx *macroFx, TApplication *app)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!macroFx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new ExplodeMacroUndo(macroFx, app));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Create Output Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class CreateOutputFxUndo : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFxP m_outputFx;
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	CreateOutputFxUndo(TFx *fx, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
		: m_outputFx(new TOutputFx), m_xshHandle(xshHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize(fx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return true; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		FxDag *fxDag = m_xshHandle->getXsheet()->getFxDag();
Toshihiro Shimizu 890ddd
		TOutputFx *outputFx = static_cast<toutputfx *="">(m_outputFx.getPointer());</toutputfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fxDag->addOutputFx(outputFx);
Toshihiro Shimizu 890ddd
		fxDag->setCurrentOutputFx(outputFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void undo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TOutputFx *outputFx = static_cast<toutputfx *="">(m_outputFx.getPointer());</toutputfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_xshHandle->getXsheet()->getFxDag()->removeOutputFx(outputFx);
Toshihiro Shimizu 890ddd
		m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QObject::tr("Create Output Fx");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize(TFx *fx)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
		TOutputFx *outputFx = static_cast<toutputfx *="">(m_outputFx.getPointer());</toutputfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (fx && !dynamic_cast<toutputfx *="">(fx))</toutputfx>
Toshihiro Shimizu 890ddd
			outputFx->getInputPort(0)->setFx(fx);
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			TOutputFx *currentOutputFx = xsh->getFxDag()->getCurrentOutputFx();
Toshihiro Shimizu 890ddd
			const TPointD &pos = currentOutputFx->getAttributes()->getDagNodePos();
Toshihiro Shimizu 890ddd
			outputFx->getAttributes()->setDagNodePos(pos + TPointD(20, 20));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::createOutputFx(TXsheetHandle *xshHandle, TFx *currentFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TUndo *undo = new CreateOutputFxUndo(currentFx, xshHandle);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	undo->redo();
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Make Output Fx Current  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::makeOutputFxCurrent(TFx *fx, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TOutputFx *outputFx = dynamic_cast<toutputfx *="">(fx);</toutputfx>
Toshihiro Shimizu 890ddd
	if (!outputFx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	if (xsh->getFxDag()->getCurrentOutputFx() == outputFx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	xsh->getFxDag()->setCurrentOutputFx(outputFx);
Toshihiro Shimizu 890ddd
	xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Connect Nodes To Xsheet  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ConnectNodesToXsheetUndo : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	std::vector<tfxp> m_fxs;</tfxp>
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ConnectNodesToXsheetUndo(const std::list<tfxp> &fxs, TXsheetHandle *xshHandle)</tfxp>
Toshihiro Shimizu 890ddd
		: m_fxs(fxs.begin(), fxs.end()), m_xshHandle(xshHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return !m_fxs.empty(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
      Due to compatibility issues from *schematicnode.cpp files, the "do" operation must be
Toshihiro Shimizu 890ddd
      accessible without scene change notifications (see TFxCommand::setParent())
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		redo_();
Toshihiro Shimizu 890ddd
		m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo_() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		FxDag *fxDag = m_xshHandle->getXsheet()->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		size_t f, fCount = m_fxs.size();
Toshihiro Shimizu 890ddd
		for (f = 0; f != fCount; ++f)
Toshihiro Shimizu 890ddd
			fxDag->addToXsheet(m_fxs[f].getPointer());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void undo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		FxDag *fxDag = m_xshHandle->getXsheet()->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		size_t f, fCount = m_fxs.size();
Toshihiro Shimizu 890ddd
		for (f = 0; f != fCount; ++f)
Toshihiro Shimizu 890ddd
			fxDag->removeFromXsheet(m_fxs[f].getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	virtual QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		QString str = QObject::tr("Connect to Xsheet  : ");
Toshihiro Shimizu 890ddd
		std::vector<tfxp>::iterator it;</tfxp>
Toshihiro Shimizu 890ddd
		for (it = m_fxs.begin(); it != m_fxs.end(); it++) {
Toshihiro Shimizu 890ddd
			if (it != m_fxs.begin())
Toshihiro Shimizu 890ddd
				str += QString(", ");
Toshihiro Shimizu 890ddd
			str += QString::fromStdWString((*it)->getFxId());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return str;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	ConnectNodesToXsheetUndo(const std::list<tfxp> &fxs, TXsheetHandle *xshHandle, bool)</tfxp>
Toshihiro Shimizu 890ddd
		: m_fxs(fxs.begin(), fxs.end()), m_xshHandle(xshHandle) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ConnectNodesToXsheetUndo::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	::FilterInsideAMacro filterInMacro = {xsh};
Toshihiro Shimizu 890ddd
	m_fxs.erase(std::remove_if(m_fxs.begin(), m_fxs.end(), filterInMacro),
Toshihiro Shimizu 890ddd
				m_fxs.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	::FilterTerminalFxs filterTerminalFxs = {xsh};
Toshihiro Shimizu 890ddd
	m_fxs.erase(std::remove_if(m_fxs.begin(), m_fxs.end(), filterTerminalFxs),
Toshihiro Shimizu 890ddd
				m_fxs.end());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::connectNodesToXsheet(const std::list<tfxp> &fxs, TXsheetHandle *xshHandle)</tfxp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new ConnectNodesToXsheetUndo(fxs, xshHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Disconnect Nodes From Xsheet  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class DisconnectNodesFromXsheetUndo : public ConnectNodesToXsheetUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	DisconnectNodesFromXsheetUndo(const std::list<tfxp> &fxs, TXsheetHandle *xshHandle)</tfxp>
Toshihiro Shimizu 890ddd
		: ConnectNodesToXsheetUndo(fxs, xshHandle, true) { initialize(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const { ConnectNodesToXsheetUndo::undo(); }
Toshihiro Shimizu 890ddd
	void undo() const { ConnectNodesToXsheetUndo::redo(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		QString str = QObject::tr("Disconnect from Xsheet  : ");
Toshihiro Shimizu 890ddd
		std::vector<tfxp>::iterator it;</tfxp>
Toshihiro Shimizu 890ddd
		for (it = m_fxs.begin(); it != m_fxs.end(); it++) {
Toshihiro Shimizu 890ddd
			if (it != m_fxs.begin())
Toshihiro Shimizu 890ddd
				str += QString(", ");
Toshihiro Shimizu 890ddd
			str += QString::fromStdWString((*it)->getFxId());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return str;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DisconnectNodesFromXsheetUndo::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	::FilterInsideAMacro filterInMacro = {xsh};
Toshihiro Shimizu 890ddd
	m_fxs.erase(std::remove_if(m_fxs.begin(), m_fxs.end(), filterInMacro),
Toshihiro Shimizu 890ddd
				m_fxs.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	::FilterNonTerminalFxs filterNonTerminalFxs = {xsh};
Toshihiro Shimizu 890ddd
	m_fxs.erase(std::remove_if(m_fxs.begin(), m_fxs.end(), filterNonTerminalFxs),
Toshihiro Shimizu 890ddd
				m_fxs.end());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::disconnectNodesFromXsheet(const std::list<tfxp> &fxs, TXsheetHandle *xshHandle)</tfxp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new DisconnectNodesFromXsheetUndo(fxs, xshHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Delete Link  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class DeleteLinksUndo : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct DynamicLink {
Toshihiro Shimizu 890ddd
		int m_groupIndex;
Toshihiro Shimizu 890ddd
		std::string m_portName;
Toshihiro Shimizu 890ddd
		TFx *m_inputFx;
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typedef std::vector<dynamiclink> DynamicLinksVector;</dynamiclink>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	std::list<tfxcommand::link> m_links; //!< The input links to remove</tfxcommand::link>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	std::list<tfxcommand::link> m_normalLinks;			//!< Actual *common* links from m_links</tfxcommand::link>
Toshihiro Shimizu 890ddd
	std::list<tfx *=""> m_terminalFxs;						//!< Fxs connected to the xsheet (represents xsheet input links)</tfx>
Toshihiro Shimizu 890ddd
														//   Why SMART pointers? No fx is deleted with this command... hmm...
Toshihiro Shimizu 890ddd
	std::map<tfx *,="" dynamiclinksvector=""> m_dynamicLinks; //!< Complete dynamic links configuration, per fx.</tfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	DeleteLinksUndo(const std::list<tfxcommand::link> &links, TXsheetHandle *xshHandle)</tfxcommand::link>
Toshihiro Shimizu 890ddd
		: m_links(links), m_xshHandle(xshHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return !m_links.empty(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return 10 << 10; } // Say, around 10 kB
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	virtual QString getHistoryString();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	DeleteLinksUndo(TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
		: m_xshHandle(xshHandle) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DeleteLinksUndo::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		static bool isInvalid(FxDag *fxDag, const TFxCommand::Link &link)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			if (link.m_index < 0)
Toshihiro Shimizu 890ddd
				return !fxDag->getTerminalFxs()->containsFx(link.m_inputFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TFx *inFx = ::getActualOut(link.m_inputFx.getPointer());
Toshihiro Shimizu 890ddd
			TFx *outFx = ::getActualIn(link.m_outputFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			return (link.m_index >= outFx->getInputPortCount()) ? true : (outFx->getInputPort(link.m_index)->getFx() != inFx);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Forget links dealing with an open macro Fx. Note that this INCLUDES inside/outside links.
Toshihiro Shimizu 890ddd
	::FilterInsideAMacro filterInMacro = {xsh};
Toshihiro Shimizu 890ddd
	m_links.erase(std::remove_if(m_links.begin(), m_links.end(), filterInMacro),
Toshihiro Shimizu 890ddd
				  m_links.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Remove invalid links
Toshihiro Shimizu 890ddd
	m_links.erase(std::remove_if(m_links.begin(), m_links.end(),
Toshihiro Shimizu 890ddd
								 tcg::bind1st(&locals::isInvalid, fxDag)),
Toshihiro Shimizu 890ddd
				  m_links.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::list<tfxcommand::link>::iterator lt, lEnd(m_links.end());</tfxcommand::link>
Toshihiro Shimizu 890ddd
	for (lt = m_links.begin(); lt != lEnd; ++lt) {
Toshihiro Shimizu 890ddd
		const TFxCommand::Link &link = *lt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (TXsheetFx *xsheetFx = dynamic_cast<txsheetfx *="">(link.m_outputFx.getPointer())) {</txsheetfx>
Toshihiro Shimizu 890ddd
			// The input fx is connected to an xsheet node - ie it's terminal
Toshihiro Shimizu 890ddd
			m_terminalFxs.push_back(link.m_inputFx.getPointer());
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFx *outputFx = link.m_outputFx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Zerary columns wrap the actual zerary fx - that is the fx holding input ports
Toshihiro Shimizu 890ddd
		if (TZeraryColumnFx *zfx = dynamic_cast<tzerarycolumnfx *="">(outputFx))</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
			outputFx = zfx->getZeraryFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFxPort *port = outputFx->getInputPort(link.m_index);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int portGroup = port->getGroupIndex();
Toshihiro Shimizu 890ddd
		if (portGroup < 0)
Toshihiro Shimizu 890ddd
			m_normalLinks.push_back(link);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (outputFx->hasDynamicPortGroups())
Toshihiro Shimizu 890ddd
			m_dynamicLinks.insert(std::make_pair(outputFx, DynamicLinksVector()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_normalLinks.sort(); // Really necessary?
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Store the complete configuration of dynamic groups - not just the ones touched by
Toshihiro Shimizu 890ddd
	// link editing, ALL of them.
Toshihiro Shimizu 890ddd
	std::map<tfx *,="" dynamiclinksvector="">::iterator dlt, dlEnd(m_dynamicLinks.end());</tfx>
Toshihiro Shimizu 890ddd
	for (dlt = m_dynamicLinks.begin(); dlt != dlEnd; ++dlt) {
Toshihiro Shimizu 890ddd
		TFx *outputFx = dlt->first;
Toshihiro Shimizu 890ddd
		DynamicLinksVector &dynLinks = dlt->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int p, pCount = outputFx->getInputPortCount();
Toshihiro Shimizu 890ddd
		for (p = 0; p != pCount; ++p) {
Toshihiro Shimizu 890ddd
			TFxPort *port = outputFx->getInputPort(p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int g = port->getGroupIndex();
Toshihiro Shimizu 890ddd
			if (g >= 0) {
Toshihiro Shimizu 890ddd
				DynamicLink dLink = {g, outputFx->getInputPortName(p), port->getFx()};
Toshihiro Shimizu 890ddd
				dynLinks.push_back(dLink);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DeleteLinksUndo::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FxDag *fxDag = m_xshHandle->getXsheet()->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Perform unlinking
Toshihiro Shimizu 890ddd
	std::list<tfxcommand::link>::const_iterator lt, lEnd(m_links.end());</tfxcommand::link>
Toshihiro Shimizu 890ddd
	for (lt = m_links.begin(); lt != lEnd; ++lt) {
Toshihiro Shimizu 890ddd
		const TFxCommand::Link &link = *lt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFx *outputFx = lt->m_outputFx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (TXsheetFx *xsheetFx = dynamic_cast<txsheetfx *="">(outputFx)) {</txsheetfx>
Toshihiro Shimizu 890ddd
			// Terminal fx link case
Toshihiro Shimizu 890ddd
			fxDag->removeFromXsheet(link.m_inputFx.getPointer());
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Actual link case
Toshihiro Shimizu 890ddd
		if (TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(outputFx))</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
			outputFx = zcfx->getZeraryFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int index = lt->m_index;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(index < outputFx->getInputPortCount());
Toshihiro Shimizu 890ddd
		if (index < outputFx->getInputPortCount())
Toshihiro Shimizu 890ddd
			outputFx->getInputPort(index)->setFx(0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DeleteLinksUndo::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FxDag *fxDag = m_xshHandle->getXsheet()->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Re-attach terminal fxs
Toshihiro Shimizu 890ddd
	std::list<tfx *="">::const_iterator ft;</tfx>
Toshihiro Shimizu 890ddd
	for (ft = m_terminalFxs.begin(); ft != m_terminalFxs.end(); ++ft) {
Toshihiro Shimizu 890ddd
		if (fxDag->checkLoop(*ft, fxDag->getXsheetFx())) {
Toshihiro Shimizu 890ddd
			assert(fxDag->checkLoop(*ft, fxDag->getXsheetFx()));
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fxDag->addToXsheet(*ft);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Restore common links
Toshihiro Shimizu 890ddd
	std::list<tfxcommand::link>::const_iterator lt, lEnd(m_normalLinks.end());</tfxcommand::link>
Toshihiro Shimizu 890ddd
	for (lt = m_normalLinks.begin(); lt != lEnd; ++lt) {
Toshihiro Shimizu 890ddd
		const TFxCommand::Link &link = *lt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int index = link.m_index;
Toshihiro Shimizu 890ddd
		TFx *inputFx = link.m_inputFx.getPointer();
Toshihiro Shimizu 890ddd
		TFx *outputFx = link.m_outputFx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (TZeraryColumnFx *zcfx = dynamic_cast<tzerarycolumnfx *="">(outputFx))</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
			outputFx = zcfx->getZeraryFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (fxDag->checkLoop(inputFx, outputFx)) {
Toshihiro Shimizu 890ddd
			assert(fxDag->checkLoop(inputFx, outputFx));
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(index < outputFx->getInputPortCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (index < outputFx->getInputPortCount())
Toshihiro Shimizu 890ddd
			outputFx->getInputPort(index)->setFx(inputFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Restore complete dynamic port groups configuration
Toshihiro Shimizu 890ddd
	std::map<tfx *,="" dynamiclinksvector="">::const_iterator dlt, dlEnd(m_dynamicLinks.end());</tfx>
Toshihiro Shimizu 890ddd
	for (dlt = m_dynamicLinks.begin(); dlt != dlEnd; ++dlt) {
Toshihiro Shimizu 890ddd
		TFx *outputFx = dlt->first;
Toshihiro Shimizu 890ddd
		const DynamicLinksVector &dynLinks = dlt->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			int g, gCount = outputFx->dynamicPortGroupsCount();
Toshihiro Shimizu 890ddd
			for (g = 0; g != gCount; ++g)
Toshihiro Shimizu 890ddd
				outputFx->clearDynamicPortGroup(g);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		size_t d, dCount = dynLinks.size();
Toshihiro Shimizu 890ddd
		for (d = 0; d != dCount; ++d) {
Toshihiro Shimizu 890ddd
			const DynamicLink &link = dynLinks[d];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TFxPort *port = new TRasterFxPort; // isAControlPort... semi-obsolete
Toshihiro Shimizu 890ddd
			port->setFx(link.m_inputFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			outputFx->addInputPort(link.m_portName, port, link.m_groupIndex);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString DeleteLinksUndo::getHistoryString()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QString str = QObject::tr("Delete Link");
Toshihiro Shimizu 890ddd
	if (!m_normalLinks.empty()) {
Toshihiro Shimizu 890ddd
		str += QString("  :  ");
Toshihiro Shimizu 890ddd
		std::list<tfxcommand::link>::const_iterator it;</tfxcommand::link>
Toshihiro Shimizu 890ddd
		for (it = m_normalLinks.begin(); it != m_normalLinks.end(); it++) {
Toshihiro Shimizu 890ddd
			if (it != m_normalLinks.begin())
Toshihiro Shimizu 890ddd
				str += QString(",  ");
Toshihiro Shimizu 890ddd
			TFxCommand::Link boundingFxs = *it;
Toshihiro Shimizu 890ddd
			str += QString("%1- -%2")
Toshihiro Shimizu 890ddd
					   .arg(QString::fromStdWString(boundingFxs.m_inputFx->getName()))
Toshihiro Shimizu 890ddd
					   .arg(QString::fromStdWString(boundingFxs.m_outputFx->getName()));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_terminalFxs.empty()) {
Toshihiro Shimizu 890ddd
		str += QString("  :  ");
Toshihiro Shimizu 890ddd
		std::list<tfxp>::const_iterator it1;</tfxp>
Toshihiro Shimizu 890ddd
		std::list<tfx *="">::const_iterator ft;</tfx>
Toshihiro Shimizu 890ddd
		for (ft = m_terminalFxs.begin(); ft != m_terminalFxs.end(); ++ft) {
Toshihiro Shimizu 890ddd
			if (ft != m_terminalFxs.begin())
Toshihiro Shimizu 890ddd
				str += QString(",  ");
Toshihiro Shimizu 890ddd
			str += QString("%1- -Xsheet")
Toshihiro Shimizu 890ddd
					   .arg(QString::fromStdWString((*it1)->getName()));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return str;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void deleteLinks(const std::list<tfxcommand::link> &links, TXsheetHandle *xshHandle)</tfxcommand::link>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new DeleteLinksUndo(links, xshHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************
Toshihiro Shimizu 890ddd
//    Delete Fx  command
Toshihiro Shimizu 890ddd
//******************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class DeleteFxOrColumnUndo : public DeleteLinksUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	TFxP m_fx;
Toshihiro Shimizu 890ddd
	TXshColumnP m_column;
Toshihiro Shimizu 890ddd
	int m_colIdx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFxP m_linkedFx;
Toshihiro Shimizu 890ddd
	std::vector<tfx *=""> m_nonTerminalInputs;</tfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	mutable std::auto_ptr<tstageobjectparams></tstageobjectparams>
Toshihiro Shimizu 890ddd
		m_columnData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
	TFxHandle *m_fxHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	using DeleteLinksUndo::m_links;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	DeleteFxOrColumnUndo(const TFxP &fx, TXsheetHandle *xshHandle, TFxHandle *fxHandle);
Toshihiro Shimizu 890ddd
	DeleteFxOrColumnUndo(int colIdx, TXsheetHandle *xshHandle, TFxHandle *fxHandle);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DeleteFxOrColumnUndo::DeleteFxOrColumnUndo(const TFxP &fx, TXsheetHandle *xshHandle, TFxHandle *fxHandle)
Toshihiro Shimizu 890ddd
	: DeleteLinksUndo(xshHandle), m_fx(fx), m_colIdx(-1), m_xshHandle(xshHandle), m_fxHandle(fxHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	initialize();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DeleteFxOrColumnUndo::DeleteFxOrColumnUndo(int colIdx, TXsheetHandle *xshHandle, TFxHandle *fxHandle)
Toshihiro Shimizu 890ddd
	: DeleteLinksUndo(xshHandle), m_colIdx(colIdx), m_xshHandle(xshHandle), m_fxHandle(fxHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	initialize();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DeleteFxOrColumnUndo::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct {
Toshihiro Shimizu 890ddd
		DeleteFxOrColumnUndo *m_this;
Toshihiro Shimizu 890ddd
		inline void getActualData(TXsheet *xsh, TFx *&ifx, TFx *&ofx)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			TFx *fx = m_this->m_fx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (!fx)
Toshihiro Shimizu 890ddd
				fx = xsh->getColumn(m_this->m_colIdx)->getFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (fx) {
Toshihiro Shimizu 890ddd
				ifx = ::getActualIn(fx);
Toshihiro Shimizu 890ddd
				ofx = ::getActualOut(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (TColumnFx *colFx = dynamic_cast<tcolumnfx *="">(ofx))</tcolumnfx>
Toshihiro Shimizu 890ddd
					m_this->m_colIdx = colFx->getColumnIndex();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			m_this->m_fx = ofx;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} locals = {this};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(m_fx || m_colIdx >= 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	TFx *ifx = 0, *ofx = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	locals.getActualData(xsh, ifx, ofx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ofx && isInsideAMacroFx(ofx, xsh)) // Macros must be exploded first
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_fx = TFxP(), m_colIdx = -1;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Assume shared ownership of the associated column, if any
Toshihiro Shimizu 890ddd
	if (m_colIdx >= 0) {
Toshihiro Shimizu 890ddd
		m_column = xsh->getColumn(m_colIdx);
Toshihiro Shimizu 890ddd
		assert(m_column);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Currently disputed, but in the previous implementation there was code suggesting
Toshihiro Shimizu 890ddd
		// that the column could have already been removed from the xsheet.
Toshihiro Shimizu 890ddd
		// Preventing that case...
Toshihiro Shimizu 890ddd
		if (!m_column->inColumnsSet()) {
Toshihiro Shimizu 890ddd
			m_fx = TFxP(), m_colIdx = -1; // Bail out as inconsistent op
Toshihiro Shimizu 890ddd
			return;						  //
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else if (TOutputFx *outputFx = dynamic_cast<toutputfx *="">(ofx)) {</toutputfx>
Toshihiro Shimizu 890ddd
		if (xsh->getFxDag()->getOutputFxCount() <= 1) {
Toshihiro Shimizu 890ddd
			// Cannot delete the last output fx
Toshihiro Shimizu 890ddd
			m_fx = TFxP();
Toshihiro Shimizu 890ddd
			assert(m_colIdx < 0);
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Store links to be re-established in the undo
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ofx) {
Toshihiro Shimizu 890ddd
		// Store the terminal output link, if any
Toshihiro Shimizu 890ddd
		if (fxDag->getTerminalFxs()->containsFx(ofx))
Toshihiro Shimizu 890ddd
			m_links.push_back(TFxCommand::Link(ofx, fxDag->getXsheetFx(), -1));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Store output links
Toshihiro Shimizu 890ddd
		int p, opCount = ofx->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
		for (p = 0; p != opCount; ++p) {
Toshihiro Shimizu 890ddd
			if (TFx *outFx = ofx->getOutputConnection(p)->getOwnerFx()) {
Toshihiro Shimizu 890ddd
				int ip, ipCount = outFx->getInputPortCount();
Toshihiro Shimizu 890ddd
				for (ip = 0; ip != ipCount; ++ip)
Toshihiro Shimizu 890ddd
					if (outFx->getInputPort(ip)->getFx() == ofx)
Toshihiro Shimizu 890ddd
						break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				assert(ip < ipCount);
Toshihiro Shimizu 890ddd
				if (ip < ipCount)
Toshihiro Shimizu 890ddd
					m_links.push_back(TFxCommand::Link(m_fx, outFx, ip));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ifx) {
Toshihiro Shimizu 890ddd
		m_linkedFx = ifx->getLinkedFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Store input links
Toshihiro Shimizu 890ddd
		int p, ipCount = ifx->getInputPortCount();
Toshihiro Shimizu 890ddd
		for (p = 0; p != ipCount; ++p) {
Toshihiro Shimizu 890ddd
			if (TFx *inputFx = ifx->getInputPort(p)->getFx()) {
Toshihiro Shimizu 890ddd
				m_links.push_back(TFxCommand::Link(inputFx, m_fx, p));
Toshihiro Shimizu 890ddd
				if (!fxDag->getTerminalFxs()->containsFx(inputFx)) // Store input fxs which DID NOT have an
Toshihiro Shimizu 890ddd
					m_nonTerminalInputs.push_back(inputFx);		   // xsheet link before the deletion
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeleteLinksUndo::initialize();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool DeleteFxOrColumnUndo::isConsistent() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return (bool(m_fx) || (m_colIdx >= 0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// NOTE: DeleteLinksUndo::isConsistent() is not checked.
Toshihiro Shimizu 890ddd
	//       This is because there could be no link to remove, and yet
Toshihiro Shimizu 890ddd
	//       the operation IS consistent.
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DeleteFxOrColumnUndo::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Store data to be restored in the undo
Toshihiro Shimizu 890ddd
	if (m_colIdx >= 0) {
Toshihiro Shimizu 890ddd
		assert(!m_columnData.get());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_columnData.reset(xsh->getStageObject(TStageObjectId::ColumnId(m_colIdx)) // Cloned, ownership acquired
Toshihiro Shimizu 890ddd
							   ->getParams());									   // However, params stored there are NOT cloned.
Toshihiro Shimizu 890ddd
	}																			   // This is fine since we're deleting the column...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Peform operation
Toshihiro Shimizu 890ddd
	FxCommandUndo::removeFxOrColumn(
Toshihiro Shimizu 890ddd
		xsh, m_fx.getPointer(), m_colIdx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged(); // Add the rest...
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void DeleteFxOrColumnUndo::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct Locals {
Toshihiro Shimizu 890ddd
		const DeleteFxOrColumnUndo *m_this;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		void insertColumnIn(TXsheet *xsh)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			m_this->insertColumn(xsh, m_this->m_column.getPointer(),
Toshihiro Shimizu 890ddd
								 m_this->m_colIdx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Restore column data
Toshihiro Shimizu 890ddd
			TStageObject *sObj = xsh->getStageObject(TStageObjectId::ColumnId(m_this->m_colIdx));
Toshihiro Shimizu 890ddd
			assert(sObj);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			sObj->assignParams(m_this->m_columnData.get(), false);
Toshihiro Shimizu 890ddd
			m_this->m_columnData.reset();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} locals = {this};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Re-add the fx/column to the xsheet
Toshihiro Shimizu 890ddd
	TFx *fx = m_fx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_column)
Toshihiro Shimizu 890ddd
		locals.insertColumnIn(xsh);
Toshihiro Shimizu 890ddd
	else if (TOutputFx *outFx = dynamic_cast<toutputfx *="">(fx))</toutputfx>
Toshihiro Shimizu 890ddd
		xsh->getFxDag()->addOutputFx(outFx);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		addFxToCurrentScene(fx, xsh, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fx) {
Toshihiro Shimizu 890ddd
		// Remove xsheet connections that became terminal due to the fx
Toshihiro Shimizu 890ddd
		// removal
Toshihiro Shimizu 890ddd
		size_t ti, tiCount = m_nonTerminalInputs.size();
Toshihiro Shimizu 890ddd
		for (ti = 0; ti != tiCount; ++ti)
Toshihiro Shimizu 890ddd
			fxDag->removeFromXsheet(m_nonTerminalInputs[ti]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Re-link parameters if necessary
Toshihiro Shimizu 890ddd
		TFx *ifx = ::getActualIn(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_linkedFx)
Toshihiro Shimizu 890ddd
			ifx->linkParams(m_linkedFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Re-establish fx links
Toshihiro Shimizu 890ddd
		DeleteLinksUndo::undo();
Toshihiro Shimizu 890ddd
	} else									// Already covered by DeleteLinksUndo::undo()
Toshihiro Shimizu 890ddd
		m_xshHandle->notifyXsheetChanged(); // in the other branch
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString DeleteFxOrColumnUndo::getHistoryString()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return QObject::tr("Delete Fx Node : %1")
Toshihiro Shimizu 890ddd
		.arg(QString::fromStdWString(m_fx->getFxId()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void deleteFxs(const std::list<tfxp> &fxs, TXsheetHandle *xshHandle, TFxHandle *fxHandle)</tfxp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TUndoManager *undoManager = TUndoManager::manager();
Toshihiro Shimizu 890ddd
	TXsheet *xsh = xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	undoManager->beginBlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::list<tfxp>::const_iterator ft, fEnd = fxs.end();</tfxp>
Toshihiro Shimizu 890ddd
	for (ft = fxs.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
		// Skip levels, as they are effectively supplied in here, AND in the deleteColumns() branch.
Toshihiro Shimizu 890ddd
		// This should NOT be performed here, though. TO BE MOVED TO deleteSelection or ABOVE, if any.
Toshihiro Shimizu 890ddd
		if (dynamic_cast<tlevelcolumnfx *="">(ft->getPointer()))</tlevelcolumnfx>
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::auto_ptr<fxcommandundo> undo(new DeleteFxOrColumnUndo(*ft, xshHandle, fxHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
		if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
			undo->redo();
Toshihiro Shimizu 890ddd
			TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	undoManager->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Remove Output Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::removeOutputFx(TFx *fx, TXsheetHandle *xshHandle, TFxHandle *fxHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TOutputFx *outputFx = dynamic_cast<toutputfx *="">(fx);</toutputfx>
Toshihiro Shimizu 890ddd
	if (!outputFx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new DeleteFxOrColumnUndo(fx, xshHandle, fxHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Delete Columns  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void deleteColumns(const std::list<int> &columns, TXsheetHandle *xshHandle, TFxHandle *fxHandle)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TUndoManager *undoManager = TUndoManager::manager();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	undoManager->beginBlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// As columns are deleted, their index changes. So, the easiest workaround is to address the
Toshihiro Shimizu 890ddd
	// columns directly, and then their (updated) column index.
Toshihiro Shimizu 890ddd
	TXsheet *xsh = xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typedef tcg::function<txshcolumn &txsheet::getcolumn="" *(txsheet::*)(int)="" const,=""> getColumn_fun;</txshcolumn>
Toshihiro Shimizu 890ddd
	tcg::binder1st<getcolumn_fun> getCol(getColumn_fun(), *xsh);</getcolumn_fun>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<txshcolumn *=""> cols(tcg::make_cast_it(columns.begin(), getCol),</txshcolumn>
Toshihiro Shimizu 890ddd
								   tcg::make_cast_it(columns.end(), getCol));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	size_t c, cCount = cols.size();
Toshihiro Shimizu 890ddd
	for (c = 0; c != cCount; ++c) {
Toshihiro Shimizu 890ddd
		std::auto_ptr<fxcommandundo> undo(new DeleteFxOrColumnUndo(cols[c]->getIndex(), xshHandle, fxHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
		if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
			undo->redo();
Toshihiro Shimizu 890ddd
			undoManager->add(undo.release());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	undoManager->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Delete Selection  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::deleteSelection(const std::list<tfxp> &fxs,</tfxp>
Toshihiro Shimizu 890ddd
								 const std::list<link> &links,
Toshihiro Shimizu 890ddd
								 const std::list<int> &columns,</int>
Toshihiro Shimizu 890ddd
								 TXsheetHandle *xshHandle, TFxHandle *fxHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Prepare selected fxs - column fxs would be done twice if the corresponding columns have
Toshihiro Shimizu 890ddd
	// been supplied for deletion too
Toshihiro Shimizu 890ddd
	::FilterColumnFxs filterColumnFxs;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::list<tfxp> filteredFxs(fxs);</tfxp>
Toshihiro Shimizu 890ddd
	filteredFxs.erase(std::remove_if(filteredFxs.begin(), filteredFxs.end(), filterColumnFxs),
Toshihiro Shimizu 890ddd
					  filteredFxs.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Perform deletions
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	deleteColumns(columns, xshHandle, fxHandle);
Toshihiro Shimizu 890ddd
	deleteFxs(filteredFxs, xshHandle, fxHandle);
Toshihiro Shimizu 890ddd
	deleteLinks(links, xshHandle);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Paste Fxs  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  NOTE: Zerary fxs should not be in the fxs list - but rather in the columns list.
Toshihiro Shimizu 890ddd
  This would allow us to forget about the zeraryColumnSize map.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  This requires changing the *selection*, though. To be done, in a later step.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoPasteFxs : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	std::list<tfxp> m_fxs;				   //!< Fxs to be pasted</tfxp>
Toshihiro Shimizu 890ddd
	std::list<txshcolumnp> m_columns;	  //!< Columns to be pasted</txshcolumnp>
Toshihiro Shimizu 890ddd
	std::vector<tfxcommand::link> m_links; //!< Links to be re-established at the redo</tfxcommand::link>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
	TFxHandle *m_fxHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoPasteFxs(const std::list<tfxp> &fxs, const std::map<tfx *,="" int=""> &zeraryFxColumnSize,</tfx></tfxp>
Toshihiro Shimizu 890ddd
				 const std::list<txshcolumnp> &columns, const TPointD &pos,</txshcolumnp>
Toshihiro Shimizu 890ddd
				 TXsheetHandle *xshHandle, TFxHandle *fxHandle,
Toshihiro Shimizu 890ddd
				 bool addOffset = true)
Toshihiro Shimizu 890ddd
		: m_fxs(fxs), m_columns(columns), m_xshHandle(xshHandle), m_fxHandle(fxHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize(zeraryFxColumnSize, pos, addOffset);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return !(m_fxs.empty() && m_columns.empty()); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	template <typename func=""></typename>
Toshihiro Shimizu 890ddd
	void for_each_fx(Func func) const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize(const std::map<tfx *,="" int=""> &zeraryFxColumnSize, const TPointD &pos, bool addOffset);</tfx>
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoPasteFxs::initialize(const std::map<tfx *,="" int=""> &zeraryFxColumnSize,</tfx>
Toshihiro Shimizu 890ddd
							  const TPointD &pos, bool addOffset)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		static void buildDagPos(TFx *fromFx, TFx *toFx, bool copyPos, bool addOffset)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			TPointD dagPos = TConst::nowhere;
Toshihiro Shimizu 890ddd
			if (copyPos) {
Toshihiro Shimizu 890ddd
				static const TPointD offset(30, 30);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				dagPos = fromFx->getAttributes()->getDagNodePos();
Toshihiro Shimizu 890ddd
				if (addOffset && (dagPos != TConst::nowhere)) // Shift may only happen if the copied
Toshihiro Shimizu 890ddd
					dagPos += offset;						  // position is well-formed.
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			toFx->getAttributes()->setDagNodePos(dagPos);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static void renamePort(TFx *fx, int p, const std::wstring &oldId, const std::wstring &newId)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			const QString &qOldId = QString::fromStdWString(oldId);
Toshihiro Shimizu 890ddd
			const QString &qNewId = QString::fromStdWString(newId);
Toshihiro Shimizu 890ddd
			const QString &qPortName = QString::fromStdString(fx->getInputPortName(p));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (qPortName.endsWith(qOldId)) {
Toshihiro Shimizu 890ddd
				QString qNewPortName = qPortName;
Toshihiro Shimizu 890ddd
				qNewPortName.replace(qOldId, qNewId);
Toshihiro Shimizu 890ddd
				fx->renamePort(qPortName.toStdString(), qNewPortName.toStdString());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static bool circularSubxsheet(TXsheet *xsh, const TXshColumnP &col)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			return xsh->checkCircularReferences(col.getPointer());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static void push_back(std::vector<tfx *=""> &fxs, TFx *fx) { fxs.push_back(fx); }</tfx>
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	bool copyDagPos = (pos != TConst::nowhere);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Initialize fxs
Toshihiro Shimizu 890ddd
	std::list<tfxp>::iterator ft, fEnd = m_fxs.end();</tfxp>
Toshihiro Shimizu 890ddd
	for (ft = m_fxs.begin(); ft != fEnd;) {
Toshihiro Shimizu 890ddd
		TFx *fx = ft->getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(!dynamic_cast<tzerarycolumnfx *="">(fx));</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (has_fx_column(fx)) {
Toshihiro Shimizu 890ddd
			// Zerary case
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Since we have no column available (WHICH IS WRONG), we'll build up a column with
Toshihiro Shimizu 890ddd
			// the specified column size
Toshihiro Shimizu 890ddd
			std::map<tfx *,="" int="">::const_iterator it = zeraryFxColumnSize.find(fx);</tfx>
Toshihiro Shimizu 890ddd
			int rows = (it == zeraryFxColumnSize.end()) ? 100 : it->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TXshZeraryFxColumn *column = new TXshZeraryFxColumn(rows);
Toshihiro Shimizu 890ddd
			TZeraryColumnFx *zcfx = column->getZeraryColumnFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			zcfx->setZeraryFx(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int op, opCount = fx->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
			for (op = opCount - 1; op >= 0; --op)				// Output links in the zerary case were
Toshihiro Shimizu 890ddd
			{													// assigned to the *actual* zerary
Toshihiro Shimizu 890ddd
				TFxPort *outPort = fx->getOutputConnection(op); // and not to a related zerary column.
Toshihiro Shimizu 890ddd
				outPort->setFx(zcfx);							// This is an FxsData fault... BUGFIX REQUEST!
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			zcfx->getAttributes()->setDagNodePos(fx->getAttributes()->getDagNodePos());
Toshihiro Shimizu 890ddd
			m_columns.push_front(column);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			ft = m_fxs.erase(ft);
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Macro case
Toshihiro Shimizu 890ddd
		if (TMacroFx *macroFx = dynamic_cast<tmacrofx *="">(fx)) {</tmacrofx>
Toshihiro Shimizu 890ddd
			const std::vector<tfxp> &inMacroFxs = macroFx->getFxs();</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			size_t f, fCount = inMacroFxs.size();
Toshihiro Shimizu 890ddd
			for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
				TFx *inFx = inMacroFxs[f].getPointer();
Toshihiro Shimizu 890ddd
				const std::wstring &oldFxId = inFx->getFxId();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// Since we're pasting a macro, we're actually pasting all of its inner fxs,
Toshihiro Shimizu 890ddd
				// which must have a different name (id) from the originals. However, such ids
Toshihiro Shimizu 890ddd
				// are actually copied in the macro's *port names* - which must therefore be
Toshihiro Shimizu 890ddd
				// redirected to the new names.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				::initializeFx(xsh, inFx);
Toshihiro Shimizu 890ddd
				const std::wstring &newFxId = inFx->getFxId();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				int ip, ipCount = macroFx->getInputPortCount();
Toshihiro Shimizu 890ddd
				for (ip = 0; ip != ipCount; ++ip)
Toshihiro Shimizu 890ddd
					locals::renamePort(macroFx, ip, oldFxId, newFxId);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		::initializeFx(xsh, fx);
Toshihiro Shimizu 890ddd
		locals::buildDagPos(fx, fx, copyDagPos, addOffset);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		++ft;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Filter columns
Toshihiro Shimizu 890ddd
	m_columns.erase(std::remove_if(m_columns.begin(), m_columns.end(), tcg::bind1st(&locals::circularSubxsheet, xsh)),
Toshihiro Shimizu 890ddd
					m_columns.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Initialize columns
Toshihiro Shimizu 890ddd
	std::list<txshcolumnp>::const_iterator ct, cEnd(m_columns.end());</txshcolumnp>
Toshihiro Shimizu 890ddd
	for (ct = m_columns.begin(); ct != cEnd; ++ct) {
Toshihiro Shimizu 890ddd
		if (TFx *cfx = (*ct)->getFx()) {
Toshihiro Shimizu 890ddd
			::initializeFx(xsh, cfx);
Toshihiro Shimizu 890ddd
			locals::buildDagPos(cfx, cfx, copyDagPos, addOffset);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Now, let's make a temporary container of all the stored fxs, both
Toshihiro Shimizu 890ddd
	// normal and column-based
Toshihiro Shimizu 890ddd
	std::vector<tfx *=""> fxs;</tfx>
Toshihiro Shimizu 890ddd
	fxs.reserve(m_fxs.size() + m_columns.size());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for_each_fx(tcg::bind1st(&locals::push_back, fxs));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// We need to store input links for these fxs
Toshihiro Shimizu 890ddd
	size_t f, fCount = fxs.size();
Toshihiro Shimizu 890ddd
	for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
		TFx *fx = fxs[f];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFx *ofx = ::getActualIn(fx);
Toshihiro Shimizu 890ddd
		fx = ::getActualOut(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int il, ilCount = ofx->getInputPortCount();
Toshihiro Shimizu 890ddd
		for (il = 0; il != ilCount; ++il) {
Toshihiro Shimizu 890ddd
			if (TFx *ifx = ofx->getInputPort(il)->getFx())
Toshihiro Shimizu 890ddd
				m_links.push_back(TFxCommand::Link(ifx, ofx, il));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Apply the required position, if any
Toshihiro Shimizu 890ddd
	if (pos != TConst::nowhere) {
Toshihiro Shimizu 890ddd
		// Then, we'll take the mean difference from pos and add it to
Toshihiro Shimizu 890ddd
		// each fx
Toshihiro Shimizu 890ddd
		TPointD middlePos;
Toshihiro Shimizu 890ddd
		int fxsCount = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::vector<tfx *="">::const_iterator ft, fEnd = fxs.end();</tfx>
Toshihiro Shimizu 890ddd
		for (ft = fxs.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
			TFx *fx = *ft;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			const TPointD &fxPos = fx->getAttributes()->getDagNodePos();
Toshihiro Shimizu 890ddd
			if (fxPos != TConst::nowhere) {
Toshihiro Shimizu 890ddd
				middlePos += fxPos;
Toshihiro Shimizu 890ddd
				++fxsCount;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (fxsCount > 0) {
Toshihiro Shimizu 890ddd
			middlePos = TPointD(middlePos.x / fxsCount, middlePos.y / fxsCount);
Toshihiro Shimizu 890ddd
			const TPointD &offset = pos - middlePos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (ft = fxs.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
				TFx *fx = *ft;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				const TPointD &fxPos = fx->getAttributes()->getDagNodePos();
Toshihiro Shimizu 890ddd
				fx->getAttributes()->setDagNodePos(fxPos + offset);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoPasteFxs::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Iterate all normal fxs
Toshihiro Shimizu 890ddd
	std::list<tfxp>::const_iterator ft, fEnd = m_fxs.end();</tfxp>
Toshihiro Shimizu 890ddd
	for (ft = m_fxs.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
		// Re-insert them in the scene
Toshihiro Shimizu 890ddd
		addFxToCurrentScene(ft->getPointer(), xsh, false);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Iterate columns
Toshihiro Shimizu 890ddd
	std::list<txshcolumnp>::const_iterator ct, cEnd = m_columns.end();</txshcolumnp>
Toshihiro Shimizu 890ddd
	for (ct = m_columns.begin(); ct != cEnd; ++ct) {
Toshihiro Shimizu 890ddd
		// Insert them
Toshihiro Shimizu 890ddd
		FxCommandUndo::insertColumn(
Toshihiro Shimizu 890ddd
			xsh, ct->getPointer(), xsh->getFirstFreeColumnIndex(),
Toshihiro Shimizu 890ddd
			true, false);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Restore links
Toshihiro Shimizu 890ddd
	size_t l, lCount = m_links.size();
Toshihiro Shimizu 890ddd
	for (l = 0; l != lCount; ++l)
Toshihiro Shimizu 890ddd
		FxCommandUndo::attach(xsh, m_links[l], false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoPasteFxs::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::list<tfxp>::const_iterator ft, fEnd = m_fxs.end();</tfxp>
Toshihiro Shimizu 890ddd
	for (ft = m_fxs.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
		TFx *fx = ft->getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		FxCommandUndo::removeFxOrColumn(xsh, fx, -1,
Toshihiro Shimizu 890ddd
										true, false); // Skip parameter links removal
Toshihiro Shimizu 890ddd
		FxCommandUndo::makeNotCurrent(m_fxHandle, fx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::list<txshcolumnp>::const_iterator ct, cEnd = m_columns.end();</txshcolumnp>
Toshihiro Shimizu 890ddd
	for (ct = m_columns.begin(); ct != cEnd; ++ct) {
Toshihiro Shimizu 890ddd
		FxCommandUndo::removeFxOrColumn(xsh, 0, (*ct)->getIndex(),
Toshihiro Shimizu 890ddd
										true, false); // Skip parameter links removal
Toshihiro Shimizu 890ddd
		FxCommandUndo::makeNotCurrent(m_fxHandle, (*ct)->getFx());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename func=""></typename>
Toshihiro Shimizu 890ddd
void UndoPasteFxs::for_each_fx(Func func) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::list<tfxp>::const_iterator ft, fEnd = m_fxs.end();</tfxp>
Toshihiro Shimizu 890ddd
	for (ft = m_fxs.begin(); ft != fEnd; ++ft)
Toshihiro Shimizu 890ddd
		func(ft->getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::list<txshcolumnp>::const_iterator ct, cEnd = m_columns.end();</txshcolumnp>
Toshihiro Shimizu 890ddd
	for (ct = m_columns.begin(); ct != cEnd; ++ct)
Toshihiro Shimizu 890ddd
		if (TFx *cfx = (*ct)->getFx())
Toshihiro Shimizu 890ddd
			func(cfx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString UndoPasteFxs::getHistoryString()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QString str = QObject::tr("Paste Fx  :  ");
Toshihiro Shimizu 890ddd
	std::list<tfxp>::const_iterator it;</tfxp>
Toshihiro Shimizu 890ddd
	for (it = m_fxs.begin(); it != m_fxs.end(); it++) {
Toshihiro Shimizu 890ddd
		if (it != m_fxs.begin())
Toshihiro Shimizu 890ddd
			str += QString(",  ");
Toshihiro Shimizu 890ddd
		str += QString("%1")
Toshihiro Shimizu 890ddd
				   .arg(QString::fromStdWString((*it)->getName()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return str;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::pasteFxs(const std::list<tfxp> &fxs, const std::map<tfx *,="" int=""> &zeraryFxColumnSize,</tfx></tfxp>
Toshihiro Shimizu 890ddd
						  const std::list<txshcolumnp> &columns, const TPointD &pos,</txshcolumnp>
Toshihiro Shimizu 890ddd
						  TXsheetHandle *xshHandle, TFxHandle *fxHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new UndoPasteFxs(</fxcommandundo>
Toshihiro Shimizu 890ddd
		fxs, zeraryFxColumnSize, columns, pos, xshHandle, fxHandle));
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Add Paste Fxs  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoAddPasteFxs : public UndoPasteFxs
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	TFxCommand::Link m_linkIn; //!< Input link to be re-established on redo
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoAddPasteFxs(TFx *inFx, const std::list<tfxp> &fxs, const std::map<tfx *,="" int=""> &zeraryFxColumnSize,</tfx></tfxp>
Toshihiro Shimizu 890ddd
					const std::list<txshcolumnp> &columns, TXsheetHandle *xshHandle, TFxHandle *fxHandle)</txshcolumnp>
Toshihiro Shimizu 890ddd
		: UndoPasteFxs(fxs, zeraryFxColumnSize, columns, TConst::nowhere,
Toshihiro Shimizu 890ddd
					   xshHandle, fxHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize(inFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize(TFx *inFx);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoAddPasteFxs::initialize(TFx *inFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!(inFx && UndoPasteFxs::isConsistent()))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// NOTE: Any zerary (shouldn't be there anyway) has already been
Toshihiro Shimizu 890ddd
	//       moved to columns at this point
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Ensure that inFx and outFx are not in a macro Fx
Toshihiro Shimizu 890ddd
	if (::isInsideAMacroFx(inFx, xsh)) {
Toshihiro Shimizu 890ddd
		m_fxs.clear(), m_columns.clear();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Get the first fx to be inserted, and follow links down
Toshihiro Shimizu 890ddd
	// (until an empty input port at index 0 is found)
Toshihiro Shimizu 890ddd
	TFx *ifx = FxCommandUndo::leftmostConnectedFx(m_fxs.front().getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Then, we have the link to be established
Toshihiro Shimizu 890ddd
	m_linkIn = TFxCommand::Link(inFx, ifx, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Furthermore, clone the group stack from inFx into each inserted fx
Toshihiro Shimizu 890ddd
	typedef tcg::function<void (*)(tfx="" *),="" *,="" fxcommandundo::clonegroupstack="" tfx=""> clone_fun;</void>
Toshihiro Shimizu 890ddd
	for_each_fx(tcg::bind1st(clone_fun(), inFx));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoAddPasteFxs::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_linkIn.m_inputFx) {
Toshihiro Shimizu 890ddd
		TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Further apply the stored link
Toshihiro Shimizu 890ddd
		FxCommandUndo::attach(xsh, m_linkIn, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Copiare l'indice di gruppo dell'fx di input
Toshihiro Shimizu 890ddd
		typedef tcg::function<void (*)(tfx="" *),="" *,="" fxcommandundo::copygroupeditlevel="" tfx=""> copy_fun;</void>
Toshihiro Shimizu 890ddd
		for_each_fx(tcg::binder1st<copy_fun>(copy_fun(), m_linkIn.m_inputFx.getPointer()));</copy_fun>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UndoPasteFxs::redo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::addPasteFxs(TFx *inFx, const std::list<tfxp> &fxs, const std::map<tfx *,="" int=""> &zeraryFxColumnSize,</tfx></tfxp>
Toshihiro Shimizu 890ddd
							 const std::list<txshcolumnp> &columns, TXsheetHandle *xshHandle, TFxHandle *fxHandle)</txshcolumnp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new UndoAddPasteFxs(</fxcommandundo>
Toshihiro Shimizu 890ddd
		inFx, fxs, zeraryFxColumnSize, columns, xshHandle, fxHandle));
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		// NOTE: (inFx == 0) is considered consistent, as long as UndoPasteFxs::isConsistent()
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Insert Paste Fxs  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoInsertPasteFxs : public UndoAddPasteFxs
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFxCommand::Link m_linkOut; //!< Output link to be re-established
Toshihiro Shimizu 890ddd
								//!< on redo
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoInsertPasteFxs(const TFxCommand::Link &link, const std::list<tfxp> &fxs,</tfxp>
Toshihiro Shimizu 890ddd
					   const std::map<tfx *,="" int=""> &zeraryFxColumnSize,</tfx>
Toshihiro Shimizu 890ddd
					   const std::list<txshcolumnp> &columns,</txshcolumnp>
Toshihiro Shimizu 890ddd
					   TXsheetHandle *xshHandle, TFxHandle *fxHandle)
Toshihiro Shimizu 890ddd
		: UndoAddPasteFxs(link.m_inputFx.getPointer(), fxs, zeraryFxColumnSize, columns, xshHandle, fxHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize(link);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize(const TFxCommand::Link &link);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoInsertPasteFxs::initialize(const TFxCommand::Link &link)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!UndoPasteFxs::isConsistent())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	TFx *inFx = link.m_inputFx.getPointer();
Toshihiro Shimizu 890ddd
	TFx *outFx = link.m_outputFx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Ensure consistency
Toshihiro Shimizu 890ddd
	if (!(inFx && outFx) || ::isInsideAMacroFx(outFx, xsh)) {
Toshihiro Shimizu 890ddd
		m_fxs.clear(), m_columns.clear();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Get the first fx to be inserted, and follow links up
Toshihiro Shimizu 890ddd
	// (to a no output fx)
Toshihiro Shimizu 890ddd
	TFx *ofx = FxCommandUndo::rightmostConnectedFx(m_fxs.front().getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Now, store the appropriate output link
Toshihiro Shimizu 890ddd
	m_linkOut = TFxCommand::Link(ofx, outFx, link.m_index);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoInsertPasteFxs::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Further apply the stored link pair
Toshihiro Shimizu 890ddd
	FxCommandUndo::attach(xsh, m_linkOut, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_linkOut.m_index < 0)
Toshihiro Shimizu 890ddd
		xsh->getFxDag()->removeFromXsheet(m_linkIn.m_inputFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UndoAddPasteFxs::redo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoInsertPasteFxs::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Reattach the original configuration
Toshihiro Shimizu 890ddd
	TFxCommand::Link orig(m_linkIn.m_inputFx, m_linkOut.m_outputFx, m_linkOut.m_index);
Toshihiro Shimizu 890ddd
	FxCommandUndo::attach(xsh, orig, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UndoAddPasteFxs::undo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::insertPasteFxs(
Toshihiro Shimizu 890ddd
	const Link &link, const std::list<tfxp> &fxs, const std::map<tfx *,="" int=""> &zeraryFxColumnSize,</tfx></tfxp>
Toshihiro Shimizu 890ddd
	const std::list<txshcolumnp> &columns, TXsheetHandle *xshHandle, TFxHandle *fxHandle)</txshcolumnp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new UndoInsertPasteFxs(</fxcommandundo>
Toshihiro Shimizu 890ddd
		link, fxs, zeraryFxColumnSize, columns, xshHandle, fxHandle));
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Replace Paste Fxs  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoReplacePasteFxs : public UndoAddPasteFxs
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<deletefxorcolumnundo> m_deleteFxUndo;</deletefxorcolumnundo>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFx *m_fx, *m_rightmostFx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoReplacePasteFxs(TFx *fx, const std::list<tfxp> &fxs, const map<tfx *,="" int=""> &zeraryFxColumnSize,</tfx></tfxp>
Toshihiro Shimizu 890ddd
						const std::list<txshcolumnp> &columns, TXsheetHandle *xshHandle, TFxHandle *fxHandle)</txshcolumnp>
Toshihiro Shimizu 890ddd
		: UndoAddPasteFxs(inFx(fx), fxs, zeraryFxColumnSize, columns, xshHandle, fxHandle), m_deleteFxUndo(new DeleteFxOrColumnUndo(fx, xshHandle, fxHandle)), m_fx(fx), m_rightmostFx()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return UndoAddPasteFxs::isConsistent() &&
Toshihiro Shimizu 890ddd
									   m_deleteFxUndo->isConsistent(); }
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	static TFx *inFx(const TFx *fx)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return (fx && fx->getInputPortCount() > 0) ? fx->getInputPort(0)->getFx() : 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoReplacePasteFxs::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_fxs.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Get the first fx to be inserted, and follow links up
Toshihiro Shimizu 890ddd
	// (to a no output fx)
Toshihiro Shimizu 890ddd
	m_rightmostFx = FxCommandUndo::rightmostConnectedFx(this->m_fxs.front().getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Then, add to the list of links to be inserted upon redo
Toshihiro Shimizu 890ddd
	int ol, olCount = m_fx->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
	for (ol = 0; ol != olCount; ++ol) {
Toshihiro Shimizu 890ddd
		TFxPort *port = m_fx->getOutputConnection(ol);
Toshihiro Shimizu 890ddd
		TFx *ownerFx = port->getOwnerFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TCG_ASSERT(port && ownerFx, continue);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int p = ::inputPortIndex(ownerFx, port);
Toshihiro Shimizu 890ddd
		TCG_ASSERT(p < ownerFx->getInputPortCount(), continue);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		this->m_links.push_back(TFxCommand::Link(m_rightmostFx, ownerFx, p));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fxDag->getTerminalFxs()->containsFx(m_fx))
Toshihiro Shimizu 890ddd
		this->m_links.push_back(TFxCommand::Link(m_rightmostFx, fxDag->getXsheetFx(), -1));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoReplacePasteFxs::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Deleting m_fx would attach its input to the xsheet, if m_fx is terminal.
Toshihiro Shimizu 890ddd
	// In our case, however, it needs to be attached to the replacement fx - so,
Toshihiro Shimizu 890ddd
	// let's detach m_fx from the xsheet
Toshihiro Shimizu 890ddd
	fxDag->removeFromXsheet(m_fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Then, delete the fx and insert the replacement. Note that this order is
Toshihiro Shimizu 890ddd
	// required to ensure the correct dag positions
Toshihiro Shimizu 890ddd
	m_deleteFxUndo->redo();
Toshihiro Shimizu 890ddd
	UndoAddPasteFxs::redo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoReplacePasteFxs::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Remove m_lastFx's output connections - UndoAddPasteFxs would try to
Toshihiro Shimizu 890ddd
	// redirect them to the replaced fx's input (due to the 'blind' detach command)
Toshihiro Shimizu 890ddd
	int ol, olCount = m_rightmostFx->getOutputConnectionCount();
Toshihiro Shimizu 890ddd
	for (ol = olCount - 1; ol >= 0; --ol)
Toshihiro Shimizu 890ddd
		if (TFxPort *port = m_rightmostFx->getOutputConnection(ol))
Toshihiro Shimizu 890ddd
			port->setFx(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fxDag->removeFromXsheet(m_rightmostFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Reverse the applied commands. Again, the order prevents 'bumped' dag positions
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UndoAddPasteFxs::undo(); // This would bridge the inserted fxs' inputs with their outputs
Toshihiro Shimizu 890ddd
	m_deleteFxUndo->undo();  // This also re-establishes the original output links
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::replacePasteFxs(TFx *inFx, const std::list<tfxp> &fxs, const map<tfx *,="" int=""> &zeraryFxColumnSize,</tfx></tfxp>
Toshihiro Shimizu 890ddd
								 const std::list<txshcolumnp> &columns, TXsheetHandle *xshHandle, TFxHandle *fxHandle)</txshcolumnp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new UndoReplacePasteFxs(inFx, fxs, zeraryFxColumnSize, columns, xshHandle, fxHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Disconnect Fxs  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoDisconnectFxs : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	std::list<tfxp> m_fxs;</tfxp>
Toshihiro Shimizu 890ddd
	TFx *m_leftFx, *m_rightFx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// NOTE: Although we'll detach only 1 input link, fxs with dynamic ports still require us
Toshihiro Shimizu 890ddd
	// to store the whole ports configuration
Toshihiro Shimizu 890ddd
	std::vector<tfxcommand::link> m_undoLinksIn, m_undoLinksOut, m_undoTerminalLinks;</tfxcommand::link>
Toshihiro Shimizu 890ddd
	std::vector<qpair<tfxp, tpointd="">> m_undoDagPos, m_redoDagPos;</qpair<tfxp,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoDisconnectFxs(const std::list<tfxp> &fxs, const QList<qpair<tfxp, tpointd="">> &oldFxPos,</qpair<tfxp,></tfxp>
Toshihiro Shimizu 890ddd
					  TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
		: m_fxs(fxs), m_xshHandle(xshHandle), m_undoDagPos(oldFxPos.begin(), oldFxPos.end())
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return !m_fxs.empty(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QObject::tr("Disconnect Fx");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static void applyPos(const QPair<tfxp, tpointd=""> &pair)</tfxp,>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		pair.first->getAttributes()->setDagNodePos(pair.second);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static void attach(TXsheet *xsh, const TFxCommand::Link &link)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		FxCommandUndo::attach(xsh, link, false);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	static void detachXsh(TXsheet *xsh, const TFxCommand::Link &link)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		xsh->getFxDag()->removeFromXsheet(link.m_inputFx.getPointer());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoDisconnectFxs::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		static QPair<tfxp, tpointd=""> originalPos(const QPair<tfxp, tpointd=""> &pair)</tfxp,></tfxp,>
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			return QPair<tfxp, tpointd="">(pair.first, pair.first->getAttributes()->getDagNodePos());</tfxp,>
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static bool contains(const std::list<tfxp> &fxs, TFx *fx)</tfxp>
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			tcg::function<tfx &tfxp::getpointer="" *(tfxp::*)()="" const,=""> getPointer_fun;</tfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			return (std::count(tcg::make_cast_it(fxs.begin(), getPointer_fun),
Toshihiro Shimizu 890ddd
							   tcg::make_cast_it(fxs.end(), getPointer_fun), fx) > 0);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Don't deal with fxs inside a macro fx
Toshihiro Shimizu 890ddd
	::FilterInsideAMacro insideAMacro_fun = {xsh};
Toshihiro Shimizu 890ddd
	if (std::find_if(m_fxs.begin(), m_fxs.end(), insideAMacro_fun) != m_fxs.end())
Toshihiro Shimizu 890ddd
		m_fxs.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_fxs.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build fxs data
Toshihiro Shimizu 890ddd
	tcg::binder1st<bool (*)(const="" std::list<tfxp=""> &, TFx *)> contains_fun(&locals::contains, m_fxs);</bool>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_leftFx = FxCommandUndo::leftmostConnectedFx(m_fxs.front().getPointer(), contains_fun);
Toshihiro Shimizu 890ddd
	m_rightFx = FxCommandUndo::rightmostConnectedFx(m_fxs.front().getPointer(), contains_fun);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Store sensible original data for the undo
Toshihiro Shimizu 890ddd
	m_undoLinksIn = FxCommandUndo::inputLinks(xsh, m_leftFx);
Toshihiro Shimizu 890ddd
	m_undoLinksOut = FxCommandUndo::outputLinks(xsh, m_rightFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<tfxcommand::link>::const_iterator lt, lEnd = m_undoLinksIn.end();</tfxcommand::link>
Toshihiro Shimizu 890ddd
	for (lt = m_undoLinksIn.begin(); lt != lEnd; ++lt)
Toshihiro Shimizu 890ddd
		if (fxDag->getTerminalFxs()->containsFx(lt->m_inputFx.getPointer()))
Toshihiro Shimizu 890ddd
			m_undoTerminalLinks.push_back(TFxCommand::Link(lt->m_inputFx.getPointer(), fxDag->getXsheetFx(), -1));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<qpair<tfxp, tpointd="">>(</qpair<tfxp,>
Toshihiro Shimizu 890ddd
		tcg::make_cast_it(m_undoDagPos.begin(), &locals::originalPos),
Toshihiro Shimizu 890ddd
		tcg::make_cast_it(m_undoDagPos.end(), &locals::originalPos))
Toshihiro Shimizu 890ddd
		.swap(m_redoDagPos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoDisconnectFxs::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Detach the first port only - I'm not sure it should really be like this, but it's
Toshihiro Shimizu 890ddd
	// legacy, and altering it would require to revise the 'simulation' procedures
Toshihiro Shimizu 890ddd
	// in fxschematicscene.cpp...  (any command simulation should be done here, btw)
Toshihiro Shimizu 890ddd
	FxCommandUndo::detachFxs(xsh, m_leftFx, m_rightFx, false);
Toshihiro Shimizu 890ddd
	if (m_leftFx->getInputPortCount() > 0)
Toshihiro Shimizu 890ddd
		m_leftFx->getInputPort(0)->setFx(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// This is also convenient, since fxs with dynamic groups will maintain all BUT 1
Toshihiro Shimizu 890ddd
	// port - thus preventing us from dealing with that, since 1 port is always available
Toshihiro Shimizu 890ddd
	// on fxs with dynamic ports...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::for_each(m_redoDagPos.begin(), m_redoDagPos.end(), applyPos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoDisconnectFxs::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	typedef void (*LinkFun)(TXsheet *xsh, const TFxCommand::Link &);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Restore the old links
Toshihiro Shimizu 890ddd
	tcg::binder1st<linkfun> attacher(&UndoDisconnectFxs::attach, xsh);</linkfun>
Toshihiro Shimizu 890ddd
	tcg::binder1st<linkfun> xshDetacher(&UndoDisconnectFxs::detachXsh, xsh);</linkfun>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::for_each(m_undoLinksIn.begin(), m_undoLinksIn.end(), attacher);
Toshihiro Shimizu 890ddd
	std::for_each(m_undoLinksOut.begin(), m_undoLinksOut.end(), attacher);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::for_each(m_undoLinksIn.begin(), m_undoLinksIn.end(), xshDetacher);
Toshihiro Shimizu 890ddd
	std::for_each(m_undoTerminalLinks.begin(), m_undoTerminalLinks.end(), attacher);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Restore old positions
Toshihiro Shimizu 890ddd
	std::for_each(m_undoDagPos.begin(), m_undoDagPos.end(), applyPos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::disconnectFxs(const std::list<tfxp> &fxs, TXsheetHandle *xshHandle,</tfxp>
Toshihiro Shimizu 890ddd
							   const QList<qpair<tfxp, tpointd="">> &fxPos)</qpair<tfxp,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new UndoDisconnectFxs(fxs, fxPos, xshHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Connect Fxs  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoConnectFxs : public UndoDisconnectFxs
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct GroupData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	TFxCommand::Link m_link;
Toshihiro Shimizu 890ddd
	std::vector<groupdata> m_undoGroupDatas;</groupdata>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoConnectFxs(const TFxCommand::Link &link, const std::list<tfxp> &fxs,</tfxp>
Toshihiro Shimizu 890ddd
				   const QList<qpair<tfxp, tpointd="">> &fxPos, TXsheetHandle *xshHandle)</qpair<tfxp,>
Toshihiro Shimizu 890ddd
		: UndoDisconnectFxs(fxs, fxPos, xshHandle), m_link(link)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return !m_fxs.empty(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static void applyPos(const QPair<tfxp, tpointd=""> &pair)</tfxp,>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		pair.first->getAttributes()->setDagNodePos(pair.second);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct UndoConnectFxs::GroupData {
Toshihiro Shimizu 890ddd
	TFx *m_fx;
Toshihiro Shimizu 890ddd
	QStack<int> m_groupIds;</int>
Toshihiro Shimizu 890ddd
	QStack<wstring> m_groupNames;</wstring>
Toshihiro Shimizu 890ddd
	int m_editingGroup;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	GroupData(TFx *fx);
Toshihiro Shimizu 890ddd
	void restore() const;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UndoConnectFxs::GroupData::GroupData(TFx *fx)
Toshihiro Shimizu 890ddd
	: m_fx(fx), m_groupIds(fx->getAttributes()->getGroupIdStack()), m_groupNames(fx->getAttributes()->getGroupNameStack()), m_editingGroup(fx->getAttributes()->getEditingGroupId())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoConnectFxs::GroupData::restore() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(!m_groupIds.empty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FxCommandUndo::cloneGroupStack(m_groupIds, m_groupNames, m_fx);
Toshihiro Shimizu 890ddd
	FxCommandUndo::copyGroupEditLevel(m_editingGroup, m_fx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoConnectFxs::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!UndoDisconnectFxs::isConsistent())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TCG_ASSERT(m_link.m_inputFx && m_link.m_outputFx,
Toshihiro Shimizu 890ddd
			   m_fxs.clear();
Toshihiro Shimizu 890ddd
			   return );
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Store sensible original data for the undo
Toshihiro Shimizu 890ddd
	m_undoGroupDatas.reserve(m_fxs.size());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::list<tfxp>::const_iterator ft, fEnd = m_fxs.end();</tfxp>
Toshihiro Shimizu 890ddd
	for (ft = m_fxs.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
		if ((*ft)->getAttributes()->isGrouped())
Toshihiro Shimizu 890ddd
			m_undoGroupDatas.push_back(GroupData((*ft).getPointer()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoConnectFxs::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UndoDisconnectFxs::redo();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Apply the new links
Toshihiro Shimizu 890ddd
	FxCommandUndo::insertFxs(xsh, m_link, m_leftFx, m_rightFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Copy the input fx's group data
Toshihiro Shimizu 890ddd
	TFx *inFx = m_link.m_inputFx.getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::list<tfxp>::const_iterator ft, fEnd = m_fxs.end();</tfxp>
Toshihiro Shimizu 890ddd
	for (ft = m_fxs.begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
		TFx *fx = (*ft).getPointer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		FxCommandUndo::cloneGroupStack(inFx, fx);
Toshihiro Shimizu 890ddd
		FxCommandUndo::copyGroupEditLevel(inFx, fx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoConnectFxs::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Undo the insert
Toshihiro Shimizu 890ddd
	FxCommandUndo::detachFxs(xsh, m_leftFx, m_rightFx);
Toshihiro Shimizu 890ddd
	FxCommandUndo::attach(xsh, m_link, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Restore the old fxs' group data
Toshihiro Shimizu 890ddd
	tcg::function<void &groupdata::restore="" (groupdata::*)()="" const,=""> restore_fun;</void>
Toshihiro Shimizu 890ddd
	std::for_each(m_undoGroupDatas.begin(), m_undoGroupDatas.end(), restore_fun);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UndoDisconnectFxs::undo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString UndoConnectFxs::getHistoryString()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return QObject::tr("Connect Fx : %1 - %2")
Toshihiro Shimizu 890ddd
		.arg(QString::fromStdWString(m_leftFx->getName()))
Toshihiro Shimizu 890ddd
		.arg(QString::fromStdWString(m_rightFx->getName()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::connectFxs(const Link &link, const std::list<tfxp> &fxs, TXsheetHandle *xshHandle,</tfxp>
Toshihiro Shimizu 890ddd
							const QList<qpair<tfxp, tpointd="">> &fxPos)</qpair<tfxp,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new UndoConnectFxs(link, fxs, fxPos, xshHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Set Parent  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class SetParentUndo : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFxP m_oldFx, m_newFx, m_parentFx;
Toshihiro Shimizu 890ddd
	int m_parentPort;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool m_removeFromXsheet;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	SetParentUndo(TFx *fx, TFx *parentFx, int parentFxPort, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
		: m_newFx(fx), m_parentFx(parentFx), m_parentPort(parentFxPort), m_xshHandle(xshHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return m_parentFx; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void redo_() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SetParentUndo::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_parentFx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// NOTE: We cannot store this directly, since it's the actual out that owns
Toshihiro Shimizu 890ddd
	// the actual in, not viceversa
Toshihiro Shimizu 890ddd
	TFx *parentFx = ::getActualIn(m_parentFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(m_parentPort < parentFx->getInputPortCount());
Toshihiro Shimizu 890ddd
	assert(m_parentPort >= 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_oldFx = parentFx->getInputPort(m_parentPort)->getFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_removeFromXsheet =											  // This is a bit odd. The legacy behavior of the
Toshihiro Shimizu 890ddd
		(m_newFx &&													  // setParent() (ie connect 2 fxs with a link, I know
Toshihiro Shimizu 890ddd
		 (m_newFx->getOutputConnectionCount() == 0) &&				  // the name is bad) command is that of *removing terminal
Toshihiro Shimizu 890ddd
		 fxDag->getTerminalFxs()->containsFx(m_newFx.getPointer()) && // links* on the input fx (m_newFx in our case).
Toshihiro Shimizu 890ddd
		 m_parentFx != fxDag->getXsheetFx());						  // I've retained this behavior since it can be handy
Toshihiro Shimizu 890ddd
																	  // for users, but only if the xsheet link is the SOLE output
Toshihiro Shimizu 890ddd
	if (::isInsideAMacroFx(m_parentFx.getPointer(), xsh) ||			  // link.
Toshihiro Shimizu 890ddd
		::isInsideAMacroFx(m_oldFx.getPointer(), xsh) ||
Toshihiro Shimizu 890ddd
		::isInsideAMacroFx(m_newFx.getPointer(), xsh))
Toshihiro Shimizu 890ddd
		m_parentFx = TFxP();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SetParentUndo::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
    Due to compatibility issues from *schematicnode.cpp files, the "do" operation cannot
Toshihiro Shimizu 890ddd
    signal changes to the scene/xsheet... but the *re*do must.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	redo_();
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SetParentUndo::redo_() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFx *parentFx = ::getActualIn(m_parentFx.getPointer());
Toshihiro Shimizu 890ddd
	FxCommandUndo::attach(xsh, m_newFx.getPointer(), parentFx, m_parentPort, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_removeFromXsheet)
Toshihiro Shimizu 890ddd
		xsh->getFxDag()->removeFromXsheet(m_newFx.getPointer());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SetParentUndo::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFx *parentFx = ::getActualIn(m_parentFx.getPointer());
Toshihiro Shimizu 890ddd
	FxCommandUndo::attach(xsh, m_oldFx.getPointer(), parentFx, m_parentPort, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_removeFromXsheet)
Toshihiro Shimizu 890ddd
		xsh->getFxDag()->addToXsheet(m_newFx.getPointer());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::setParent(TFx *fx, TFx *parentFx, int parentFxPort, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (dynamic_cast<txsheetfx *="">(parentFx) || parentFxPort < 0) {</txsheetfx>
Toshihiro Shimizu 890ddd
		std::auto_ptr<connectnodestoxsheetundo> undo(new ConnectNodesToXsheetUndo(std::list<tfxp>(1, fx), xshHandle));</tfxp></connectnodestoxsheetundo>
Toshihiro Shimizu 890ddd
		if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
			undo->redo_();
Toshihiro Shimizu 890ddd
			TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		std::auto_ptr<setparentundo> undo(new SetParentUndo(fx, parentFx, parentFxPort, xshHandle));</setparentundo>
Toshihiro Shimizu 890ddd
		if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
			undo->redo_();
Toshihiro Shimizu 890ddd
			TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Rename Fx  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoRenameFx : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFxP m_fx;
Toshihiro Shimizu 890ddd
	std::wstring m_newName, m_oldName;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoRenameFx(TFx *fx, const std::wstring &newName, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
		: m_fx(fx), m_newName(newName), m_oldName(::getActualIn(fx)->getName()), m_xshHandle(xshHandle) { assert(fx); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return true; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		redo_();
Toshihiro Shimizu 890ddd
		m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo_() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		::getActualIn(m_fx.getPointer())->setName(m_newName);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void undo() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		::getActualIn(m_fx.getPointer())->setName(m_oldName);
Toshihiro Shimizu 890ddd
		m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QObject::tr("Rename Fx : %1 > %2")
Toshihiro Shimizu 890ddd
			.arg(QString::fromStdWString(m_oldName))
Toshihiro Shimizu 890ddd
			.arg(QString::fromStdWString(m_newName));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::renameFx(TFx *fx, const std::wstring &newName, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!fx)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::auto_ptr<undorenamefx> undo(new UndoRenameFx(fx, newName, xshHandle));</undorenamefx>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo_();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Group Fxs  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoGroupFxs : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	struct GroupData {
Toshihiro Shimizu 890ddd
		TFxP m_fx;
Toshihiro Shimizu 890ddd
		mutable int m_groupIndex; //! AKA group \a position (not \a id).
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		GroupData(const TFxP &fx, int groupIdx = -1)
Toshihiro Shimizu 890ddd
			: m_fx(fx), m_groupIndex(groupIdx) {}
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	std::vector<groupdata> m_groupData;</groupdata>
Toshihiro Shimizu 890ddd
	int m_groupId;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoGroupFxs(const std::list<tfxp> &fxs, TXsheetHandle *xshHandle)</tfxp>
Toshihiro Shimizu 890ddd
		: m_groupData(fxs.begin(), fxs.end()), m_xshHandle(xshHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return !m_groupData.empty(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	virtual QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QObject::tr("Group Fx");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	UndoGroupFxs(int groupId, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
		: m_groupId(groupId), m_xshHandle(xshHandle) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoGroupFxs::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		inline static bool isXsheetFx(const GroupData &gd)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			return dynamic_cast<txsheet *="">(gd.m_fx.getPointer());</txsheet>
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build a group id for the new group
Toshihiro Shimizu 890ddd
	m_groupId = fxDag->getNewGroupId();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// The xsheet fx must never be grouped
Toshihiro Shimizu 890ddd
	m_groupData.erase(
Toshihiro Shimizu 890ddd
		std::remove_if(m_groupData.begin(), m_groupData.end(), &locals::isXsheetFx),
Toshihiro Shimizu 890ddd
		m_groupData.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Scan for macro fxs. A macro's internal fxs must be added to the group data, too
Toshihiro Shimizu 890ddd
	// Yep, this is one of the few fx commands that do not require macro explosion.
Toshihiro Shimizu 890ddd
	size_t g, gCount = m_groupData.size();
Toshihiro Shimizu 890ddd
	for (g = 0; g != gCount; ++g) {
Toshihiro Shimizu 890ddd
		if (TMacroFx *macro = dynamic_cast<tmacrofx *="">(m_groupData[g].m_fx.getPointer())) {</tmacrofx>
Toshihiro Shimizu 890ddd
			const std::vector<tfxp> &internalFxs = macro->getFxs();</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			std::vector<tfxp>::const_iterator ft, fEnd = internalFxs.end();</tfxp>
Toshihiro Shimizu 890ddd
			for (ft = internalFxs.begin(); ft != fEnd; ++ft)
Toshihiro Shimizu 890ddd
				m_groupData.push_back(*ft);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoGroupFxs::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const std::wstring groupName = L"Group " + toWideString(m_groupId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<groupdata>::const_iterator gt, gEnd = m_groupData.end();</groupdata>
Toshihiro Shimizu 890ddd
	for (gt = m_groupData.begin(); gt != gEnd; ++gt) {
Toshihiro Shimizu 890ddd
		// Insert the group id in the fx
Toshihiro Shimizu 890ddd
		gt->m_groupIndex = gt->m_fx->getAttributes()->setGroupId(m_groupId);
Toshihiro Shimizu 890ddd
		gt->m_fx->getAttributes()->setGroupName(groupName);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoGroupFxs::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<groupdata>::const_iterator gt, gEnd = m_groupData.end();</groupdata>
Toshihiro Shimizu 890ddd
	for (gt = m_groupData.begin(); gt != gEnd; ++gt) {
Toshihiro Shimizu 890ddd
		TCG_ASSERT(gt->m_groupIndex >= 0, continue);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Insert the group id in the fx
Toshihiro Shimizu 890ddd
		gt->m_fx->getAttributes()->removeGroupId(gt->m_groupIndex);
Toshihiro Shimizu 890ddd
		gt->m_fx->getAttributes()->removeGroupName(gt->m_groupIndex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		gt->m_groupIndex = -1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::groupFxs(const std::list<tfxp> &fxs, TXsheetHandle *xshHandle)</tfxp>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new UndoGroupFxs(fxs, xshHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Ungroup Fxs  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoUngroupFxs : public UndoGroupFxs
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoUngroupFxs(int groupId, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
		: UndoGroupFxs(groupId, xshHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const { UndoGroupFxs::undo(); }
Toshihiro Shimizu 890ddd
	void undo() const { UndoGroupFxs::redo(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QObject::tr("Ungroup Fx");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoUngroupFxs::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct {
Toshihiro Shimizu 890ddd
		UndoUngroupFxs *m_this;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		void scanFxForGroup(TFx *fx)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			if (fx) {
Toshihiro Shimizu 890ddd
				const QStack<int> &groupStack = fx->getAttributes()->getGroupIdStack();</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				int groupIdx = groupStack.indexOf(m_this->m_groupId); // Returns -1 if not found
Toshihiro Shimizu 890ddd
				if (groupIdx >= 0)
Toshihiro Shimizu 890ddd
					m_this->m_groupData.push_back(GroupData(fx, groupIdx));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} locals = {this};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	FxDag *fxDag = xsh->getFxDag();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// We must iterate the xsheet's fxs pool and look for fxs with the specified
Toshihiro Shimizu 890ddd
	// group id
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Search column fxs
Toshihiro Shimizu 890ddd
	int c, cCount = xsh->getColumnCount();
Toshihiro Shimizu 890ddd
	for (c = 0; c != cCount; ++c) {
Toshihiro Shimizu 890ddd
		TXshColumn *column = xsh->getColumn(c);
Toshihiro Shimizu 890ddd
		assert(column);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		locals.scanFxForGroup(column->getFx());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Search normal fxs (not column ones)
Toshihiro Shimizu 890ddd
	TFxSet *internalFxs = fxDag->getInternalFxs();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int f, fCount = internalFxs->getFxCount();
Toshihiro Shimizu 890ddd
	for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
		TFx *fx = internalFxs->getFx(f);
Toshihiro Shimizu 890ddd
		locals.scanFxForGroup(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (TMacroFx *macroFx = dynamic_cast<tmacrofx *="">(fx)) {</tmacrofx>
Toshihiro Shimizu 890ddd
			// Search internal macro fxs
Toshihiro Shimizu 890ddd
			const std::vector<tfxp> &fxs = macroFx->getFxs();</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			std::vector<tfxp>::const_iterator ft, fEnd = fxs.end();</tfxp>
Toshihiro Shimizu 890ddd
			for (ft = fxs.begin(); ft != fEnd; ++ft)
Toshihiro Shimizu 890ddd
				locals.scanFxForGroup(ft->getPointer());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Search output fxs
Toshihiro Shimizu 890ddd
	int o, oCount = fxDag->getOutputFxCount();
Toshihiro Shimizu 890ddd
	for (o = 0; o != oCount; ++o)
Toshihiro Shimizu 890ddd
		locals.scanFxForGroup(fxDag->getOutputFx(o));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::ungroupFxs(int groupId, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<fxcommandundo> undo(new UndoUngroupFxs(groupId, xshHandle));</fxcommandundo>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo();
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
//    Rename Group  command
Toshihiro Shimizu 890ddd
//**********************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UndoRenameGroup : public FxCommandUndo
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<undogroupfxs::groupdata> m_groupData;</undogroupfxs::groupdata>
Toshihiro Shimizu 890ddd
	std::wstring m_oldGroupName, m_newGroupName;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXsheetHandle *m_xshHandle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UndoRenameGroup(const std::list<tfxp> &fxs, const std::wstring &newGroupName, bool fromEditor, TXsheetHandle *xshHandle)</tfxp>
Toshihiro Shimizu 890ddd
		: m_groupData(fxs.begin(), fxs.end()), m_newGroupName(newGroupName), m_xshHandle(xshHandle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		initialize(fromEditor);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isConsistent() const { return !m_groupData.empty(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo() const;
Toshihiro Shimizu 890ddd
	void undo() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void redo_() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getSize() const { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString getHistoryString()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return QObject::tr("Rename Group  : %1 > %2")
Toshihiro Shimizu 890ddd
			.arg(QString::fromStdWString(m_oldGroupName))
Toshihiro Shimizu 890ddd
			.arg(QString::fromStdWString(m_newGroupName));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void initialize(bool fromEditor);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoRenameGroup::initialize(bool fromEditor)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		inline static bool isInvalid(const UndoGroupFxs::GroupData &gd) { return (gd.m_groupIndex < 0); }
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_groupData.empty()) {
Toshihiro Shimizu 890ddd
		m_oldGroupName = m_groupData.front().m_fx->getAttributes()->getGroupName(fromEditor);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Extract group indices
Toshihiro Shimizu 890ddd
		std::vector<undogroupfxs::groupdata>::const_iterator gt, gEnd = m_groupData.end();</undogroupfxs::groupdata>
Toshihiro Shimizu 890ddd
		for (gt = m_groupData.begin(); gt != gEnd; ++gt) {
Toshihiro Shimizu 890ddd
			const QStack<std::wstring> &groupNamesStack =</std::wstring>
Toshihiro Shimizu 890ddd
				gt->m_fx->getAttributes()->getGroupNameStack();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			gt->m_groupIndex = groupNamesStack.indexOf(m_oldGroupName); // Returns -1 if not found
Toshihiro Shimizu 890ddd
			assert(gt->m_groupIndex >= 0);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_groupData.erase(std::remove_if(m_groupData.begin(), m_groupData.end(), &locals::isInvalid),
Toshihiro Shimizu 890ddd
					  m_groupData.end());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoRenameGroup::redo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	redo_();
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoRenameGroup::redo_() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<undogroupfxs::groupdata>::const_iterator gt, gEnd = m_groupData.end();</undogroupfxs::groupdata>
Toshihiro Shimizu 890ddd
	for (gt = m_groupData.begin(); gt != gEnd; ++gt) {
Toshihiro Shimizu 890ddd
		gt->m_fx->getAttributes()->removeGroupName(gt->m_groupIndex);
Toshihiro Shimizu 890ddd
		gt->m_fx->getAttributes()->setGroupName(m_newGroupName, gt->m_groupIndex);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UndoRenameGroup::undo() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<undogroupfxs::groupdata>::const_iterator gt, gEnd = m_groupData.end();</undogroupfxs::groupdata>
Toshihiro Shimizu 890ddd
	for (gt = m_groupData.begin(); gt != gEnd; ++gt) {
Toshihiro Shimizu 890ddd
		gt->m_fx->getAttributes()->removeGroupName(gt->m_groupIndex);
Toshihiro Shimizu 890ddd
		gt->m_fx->getAttributes()->setGroupName(m_oldGroupName, gt->m_groupIndex);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCommand::renameGroup(const std::list<tfxp> &fxs, const std::wstring &name,</tfxp>
Toshihiro Shimizu 890ddd
							 bool fromEditor, TXsheetHandle *xshHandle)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<undorenamegroup> undo(new UndoRenameGroup(fxs, name, fromEditor, xshHandle));</undorenamegroup>
Toshihiro Shimizu 890ddd
	if (undo->isConsistent()) {
Toshihiro Shimizu 890ddd
		undo->redo_(); // Same schematic nodes problem as above...   :(
Toshihiro Shimizu 890ddd
		TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}