ListBox(bool useOsgText = false):
	ListBoxBase("listbox"),
	_lbp(new ListBoxPopup(useOsgText)) {
		ButtonArrow* ba = new ButtonArrow();

		ba->renderArrow(
			_fontSize,
			_lineWidth,
			osgWidget::Color(_lineColor, 1.0f),
			osgWidget::Color(_fillColor, 1.0f)
		);

		osgWidget::Box*    drop  = new osgWidget::Box("drop", osgWidget::Box::HORIZONTAL);
		osgWidget::Widget* arrow = new osgWidget::Widget("arrow", _fontSize * 2.0f, _fontSize);
		osgWidget::Widget* label = 0;

		if(useOsgText) {
			osgWidget::Label* l = new osgWidget::Label("testing");

			l->setFont("fonts/Vera.ttf");
			l->setFontSize(_fontSize);
			l->setFontColor(osg::Vec4(_lineColor, 1.0f));
			l->setLabel("Choose a font...");

			label = l;
		}

		else {
			osgPairo::Label* l = new osgPairo::Label("testing", _font.get());

			l->getText()->setColor(_lineColor);
			l->getText()->setText("Choose a font...");
			l->setColor(osgWidget::Color(_fillColor, 1.0f));
			l->textUpdated();

			label = l;
		}

		arrow->setImage(ba, true, true);
		arrow->setPadLeft(30.0f);

		drop->getBackground()->setColor(osgWidget::Color(_fillColor, 1.0f));
		drop->addWidget(label);
		drop->addWidget(arrow);
		drop->setEventMask(0x0);
		drop->resize();

		setWindow(drop);
		resizeFrame(drop->getWidth(), drop->getHeight());
	}
	ListBoxPopup(bool useOsgText = false):
	ListBoxBase("listboxPopup") {
		osgPairo::Font::FontList fl;

		osgPairo::Font::getFontList(fl, false);

		osgWidget::Box* fonts = new osgWidget::Box("fonts", osgWidget::Box::VERTICAL, true);

		for(osgPairo::Font::FontList::iterator i = fl.begin(); i != fl.end(); i++) {
			osgWidget::Widget* label = 0;

			if(useOsgText) {
		 		osgWidget::Label* l = new osgWidget::Label(*i + "label");

				l->setFont("fonts/Vera.ttf");
				l->setFontSize(_fontSize);
				l->setFontColor(osg::Vec4(_lineColor, 1.0f));
				l->setLabel(*i);

				label = l;
			}

			else {
				osgPairo::Label* l = new osgPairo::Label(*i + "label", _font.get());

				l->getText()->setColor(_lineColor);
				l->getText()->setText(*i);
				l->textUpdated();
				//l->setEventMask(osgWidget::EVENT_MASK_MOUSE_MOVE);
				//l->addCallback(new osgWidget::Callback(&overCallback, osgWidget::EVENT_MOUSE_ENTER));
				//l->addCallback(new osgWidget::Callback(&overCallback, osgWidget::EVENT_MOUSE_LEAVE));

				label = l;
			}

			label->setAlignHorizontal(osgWidget::Widget::HA_LEFT);
			label->setColor(osg::Vec4(_fillColor, 1.0f));
			label->setCanFill(true);
			label->setPadding(1.0f);

			fonts->addWidget(label);
		}

		fonts->getBackground()->setColor(osgWidget::Color(_fillColor, 1.0f));

		setWindow(fonts);
		resizeFrame(fonts->getWidth(), fonts->getHeight());
	}
void TonemapperThread::run() {
	qDebug("TMthread::begin thread, size=%d, gamma=%f",xsize, pregamma);
	lock.lockForRead();
	if (opts.xsize==originalxsize && opts.pregamma==1.0f) {
		//original goes into tone mapping
		qDebug("TMthread::original goes into tone mapping");
		fetch("/original.pfs");
		status=from_tm;
		colorspaceconversion=true;
		emit setMaximumSteps(2);
	} else if (opts.xsize==xsize && opts.pregamma==1.0f) {
		//resized goes into tone mapping
		qDebug("TMthread::resized goes into tone mapping");
		fetch("/after_resize.pfs");
		status=from_tm;
		colorspaceconversion=true;
		emit setMaximumSteps(2);
	} else if ( (opts.xsize==xsize && opts.pregamma==pregamma) || (opts.xsize==originalxsize && xsize==-1 && opts.pregamma==pregamma) ) {
		//after_pregamma goes into tone mapping
		qDebug("TMthread::after_pregamma goes into tone mapping");
		fetch("/after_pregamma.pfs");
		status=from_tm;
		emit setMaximumSteps(2);
	} else if (opts.xsize==xsize) {
		//resized goes into pregamma
		qDebug("TMthread::resized goes into pregamma");
		fetch("/after_resize.pfs");
		status=from_pregamma;
		emit setMaximumSteps(3);
	} else if (opts.xsize==originalxsize) {
		//original goes into pregamma
		qDebug("TMthread::original goes into pregamma");
		fetch("/original.pfs");
		status=from_pregamma;
		emit setMaximumSteps(3);
	} else {
		//original goes into resize
		qDebug("TMthread::original goes into resize");
		fetch("/original.pfs");
		status=from_resize;
		emit setMaximumSteps(4);
	}
	emit advanceCurrentProgress();
	lock.unlock();


	if (status==from_resize) {
		assert(opts.xsize!=originalxsize);
		qDebug("TMthread:: executing resize step");
		pfs::Frame *resized=resizeFrame(workingframe, opts.xsize);
		lock.lockForWrite();
		swap(resized,"/after_resize.pfs");
		xsize=opts.xsize;
		pregamma=-1;
		lock.unlock();
		delete workingframe;
		workingframe=resized;
		status=from_pregamma;
		emit advanceCurrentProgress();
	}
	if (status==from_pregamma) {
		qDebug("TMthread:: executing pregamma step");
		applyGammaFrame( workingframe, opts.pregamma );
		lock.lockForWrite();
		swap(workingframe,"/after_pregamma.pfs");
		pregamma=opts.pregamma;
		if (opts.xsize==originalxsize)
			xsize=-1;
		else
			xsize=opts.xsize;
		lock.unlock();
		status=from_tm;
		emit advanceCurrentProgress();
	}
	if (status==from_tm) {
		qDebug("TMthread:: executing tone mapping step");
		if (colorspaceconversion)
			workingframe->convertRGBChannelsToXYZ();
		pfs::Frame *result=NULL;
		switch (opts.tmoperator) {
		case mantiuk:
			result=pfstmo_mantiuk06(workingframe,
			opts.operator_options.mantiukoptions.contrastfactor,
			opts.operator_options.mantiukoptions.saturationfactor,
			opts.operator_options.mantiukoptions.detailfactor,
			opts.operator_options.mantiukoptions.contrastequalization);
		break;
		case fattal:
			//fattal is NOT even reentrant! (problem in PDE solving)
			//therefore I need to use a mutex here
			lock.lockForWrite();
			result=pfstmo_fattal02(workingframe,
			opts.operator_options.fattaloptions.alpha,
			opts.operator_options.fattaloptions.beta,
			opts.operator_options.fattaloptions.color,
			opts.operator_options.fattaloptions.noiseredux,
			opts.operator_options.fattaloptions.newfattal);
			lock.unlock();
		break;
		case ashikhmin:
			result=pfstmo_ashikhmin02(workingframe,
			opts.operator_options.ashikhminoptions.simple,
			opts.operator_options.ashikhminoptions.lct,
			opts.operator_options.ashikhminoptions.eq2 ? 2 : 4);
		break;
		case durand:
			//even durand seems to be not reentrant
			lock.lockForWrite();
			result=pfstmo_durand02(workingframe,
			opts.operator_options.durandoptions.spatial,
			opts.operator_options.durandoptions.range,
			opts.operator_options.durandoptions.base);
			lock.unlock();
		break;
		case drago:
			result=pfstmo_drago03(workingframe, opts.operator_options.dragooptions.bias);
		break;
		case pattanaik:
			result=pfstmo_pattanaik00(workingframe,
			opts.operator_options.pattanaikoptions.local,
			opts.operator_options.pattanaikoptions.multiplier,
			opts.operator_options.pattanaikoptions.cone,
			opts.operator_options.pattanaikoptions.rod,
			opts.operator_options.pattanaikoptions.autolum);
		break;
		case reinhard02:
			result=pfstmo_reinhard02(workingframe,
			opts.operator_options.reinhard02options.key,
			opts.operator_options.reinhard02options.phi,
			opts.operator_options.reinhard02options.range,
			opts.operator_options.reinhard02options.lower,
			opts.operator_options.reinhard02options.upper,
			opts.operator_options.reinhard02options.scales);
		break;
		case reinhard05:
			result=pfstmo_reinhard05(workingframe,
			opts.operator_options.reinhard05options.brightness,
			opts.operator_options.reinhard05options.chromaticAdaptation,
			opts.operator_options.reinhard05options.lightAdaptation);
		break;
		} //switch (opts.tmoperator)
		emit advanceCurrentProgress();
		assert(result!=NULL);
		delete workingframe;
		const QImage& res=fromLDRPFStoQImage(result);
		delete result;
		emit ImageComputed(res,&opts);
	} //if (status==from_tm)
// 	emit finished();
}