
function SSCollection()
{
}

// Класс управления обработчиками подвидов состояния
// Подключить обработчик можно методом addSubStateCtrl. Обработчик - объект,
// имеющий два метода - save и load (вернуть состояние в виде строки и загрузить состояние
// из строки, соответственно).
// Методы save и load данного класса соответственно сохраняют и загружают состояние всей страницы
// в (из) строку(и). Формат - 'имя_обработчика{состояние}'.
// При сохранении или загрузке состояния страницы вызываются соответствующие методы обработчиков
function StateCtrl()
{
	this.subStateCtrls = new SSCollection();
	
	this.addSubStateCtrl = SCTRL_addSubStateCtrl;
	this.getSubStateCtrl = SCTRL_getSubStateCtrl;
	this.load = SCTRL_load;
	this.save = SCTRL_save;
}

function SCTRL_addSubStateCtrl(name, ctrl)
{
	this.subStateCtrls[name] = ctrl;
}

function SCTRL_getSubStateCtrl(name)
{
	return this.subStateCtrls[name];
}

function SCTRL_load(state)
{
	if (state == null || state == "")
		return;
		
	var str = state;
	while (str != "")
	{
		var i = str.indexOf('{');
		if (i <= 0)
			break;
		
		var name = str.substring(0, i);
		str = str.substring(i+1);
		if (str == "")
			break;
			
		var bcnt = 1;
		var len = str.length;
		for (i = 0; i < len; i++)
		{
			var c = str.charAt(i);
			if (c == '{')
			{
				bcnt++;
				continue;
			}
			if (c == '}')
			{
				bcnt--;
				if (bcnt == 0)
					break;
			}
		}
		if (i == len)
			break;
		var sstr = str.substring(0, i);
		str = str.substring(i+1);
		var ctrl = this.subStateCtrls[name];
		if (ctrl != null)
			ctrl.load(sstr, state);
	}
}

function SCTRL_save()
{
	var str = "";
	var i;
	for (i in this.subStateCtrls)
	{
		var ss = this.subStateCtrls[i].save();
		if (typeof(ss) == "undefined" || ss == null || (ss+"") == "")
			continue;
		str += i + '{' + ss + '}';
	}
	return str;
}

var stateCtrl = new StateCtrl();

// получение объекта состояния из окна подчиненного фрейма
function getSubState(name)
{
	var ssCtrl = stateCtrl.getSubStateCtrl(name);
	if (ssCtrl != null && ssCtrl.get != null)
	{
		return ssCtrl.get();
	}
}

window.getSubState = getSubState;


// Типовой вариант обработчика:
// Хранитель состояния подчиненного фрейма
function FrameState(frameName)
{
	this.state;
	this.frame;
	this.frameName = frameName;
	
	this.getFrame = FRST_getFrame;
	
	this.load = FRST_load;
	this.reload = FRST_reload;
	this.save = FRST_save;
	this.get = FRST_get;
	this.clear = FRST_clear;
}

function FRST_getFrame()
{
	if (this.frame == null)
	{
		var frameObj = null;
		if (frames != null){
			frameObj = frames[this.frameName];
		}else if (window.frames != null){
			frameObj = window.frames[this.frameName];
		}else{
			frameObj = document.getElementById(this.frameName);
			if (frameObj == null)
				return;
			frameObj = frames[this.frameName];
		}
		this.frame = frameObj;
	}
	return this.frame;
}

function FRST_load(st)
{
	if (st == null || st == "")
		return;
	this.state = st;
	var frame = this.getFrame();
	if (frame == null)
		return;
	var wnd = frame.window;
	if (wnd.stateLoad != null)
		wnd.stateLoad(this.state);
}

function FRST_reload()
{
	var frame = this.getFrame();
	if (this.state != null && frame != null)
	{
		var wnd = frame.window;
		if (wnd.stateLoad != null)
			wnd.stateLoad(this.state);
	}
}

function FRST_save()
{
	var frame = this.getFrame();
	if (frame == null)
		return this.state;
	try{
		if (frame.frameElement == null)
			return this.state;
	}catch (e){
		return this.state;
	}
	if (frame.frameElement.style.display == 'none')
		return this.state;
	var wnd = frame.window;
	if (wnd.stateSave != null)
		this.state = wnd.stateSave();
	return this.state;
}

function FRST_get()
{
	return this.state;
}

function FRST_clear()
{
	this.state = null;
}


// Хранители состояний подчиненных фреймов используются
// и для связи с фреймами, поэтому организованы в коллекцию:
// Коллекция состояний подчиненных фреймов
function FSCollection()
{
}

function FrameStateCollection()
{
	this.frames = new FSCollection();
	
	this.create = FRSTC_create;
	this.get = FRSTC_get;
}

function FRSTC_create(frame_name)
{
	var frmState = new FrameState(frame_name);
	try{
		this.frames[frame_name] = frmState;
	}catch (e){
	}
	return frmState;
}

function FRSTC_get(name)
{
	return this.frames[name];
}

var frameStates = new FrameStateCollection();


// 23.03.06 amoro:
// Получение упакованной информации о состоянии списка во фрейме
function getPackedFrameState(fname)
{
	var frm = null;
	if (frames != null)
	{
		frm = frames[fname];
		if (frm == null)
			return null;
	}
	else
	{
		frm = document.getElementById(fname);
		if (frm == null)
			return null;
		frm = frames[fname];
		if (frm == null)
			return null;
	}
	var wnd = frm.window;
	if (typeof(wnd.getPackedListState) != "undefined")
	{
		var st = wnd.getPackedListState();
		return (fname + '*' + st);
	}
	return null;
}

