TEST( Notifier, TestOfNotificationUseAfterRelease )
{
	Notifier notifier;

	TestClazzReleased* pReleasedNode = new TestClazzReleased( notifier );
	pReleasedNode->init();

	CCNode* pHolder = new CCNode();
	pHolder->init();
	notifier.addNotification( getNotificationTestUseAfterRelease(), {pHolder, &CCNode::removeAllChildren } );

	EXPECT_EQ( 1u, pReleasedNode->retainCount() );
	EXPECT_EQ( 1u, pHolder->retainCount() );

	pHolder->addChild( pReleasedNode );

	EXPECT_EQ( 2u, pReleasedNode->retainCount() );
	EXPECT_EQ( 1u, pHolder->retainCount() );

	pReleasedNode->release();

	EXPECT_EQ( 1u, pReleasedNode->retainCount() );
	EXPECT_EQ( 1u, pHolder->retainCount() );

	//OLD: Now when we notify we have problem. We have use after release.
	//NEW: Now everything should work because we mark second notification as toRemove so we simply skip it :)
	notifier.notify( getNotificationTestUseAfterRelease() );

	pHolder->release();
}
TEST( Notifier, TestOfNotificationChangesStack )
{
	Notifier notifier;
	TestClazz testClazz;

	notifier.addNotification( getNotificationTest1(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );
	notifier.addNotification( getNotificationTest2(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );

	EXPECT_EQ( 0, testClazz.deliveredCount );
	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 1, testClazz.deliveredCount );

	notifier.removeAllForObject( &testClazz );
	notifier.removeAllForObject( &testClazz );
	notifier.notify( getNotificationTest3(), 0x01 );
}
TEST( Notifier, DISABLED_TestOfNotificationChangesStackDoubleCommands )
{
	Notifier notifier;
	TestClazz testClazz;

	notifier.addNotification( getNotificationTest1(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );
	notifier.addNotification( getNotificationTest2(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );

	EXPECT_EQ( 0, testClazz.deliveredCount );
	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 1, testClazz.deliveredCount );

	notifier.removeAllForObject( &testClazz );
	notifier.removeAllForObject( &testClazz );

	notifier.addNotification( getNotificationTest1(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );
	notifier.addNotification( getNotificationTest2(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );

	notifier.notify( getNotificationTest3(), 0x01 );

	EXPECT_EQ( 1, testClazz.deliveredCount );
	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 2, testClazz.deliveredCount );

	notifier.addNotification( getNotificationTest1(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );
	//Now we have double notification
	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 4, testClazz.deliveredCount );

	notifier.removeNotification( &testClazz, getNotificationTest1() );
	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 4, testClazz.deliveredCount );
}
TEST( Notifier, TestOfNotification )
{
	Notifier notifier;
	TestClazz testClazz;

	notifier.addNotification( getNotificationTest1(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );

	EXPECT_EQ( 0, testClazz.deliveredCount );

	notifier.notify( getNotificationTest1() );

	EXPECT_EQ( 1, testClazz.deliveredCount );

	notifier.notify( getNotificationTest1() );
	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 3, testClazz.deliveredCount );

	notifier.removeAllForObject( &testClazz );
	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 3, testClazz.deliveredCount );

	notifier.addNotification( getNotificationTest1(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );
	EXPECT_EQ( 3, testClazz.deliveredCount );

	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 4, testClazz.deliveredCount );

	notifier.removeNotification( &testClazz, getNotificationTest1() );
	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 4, testClazz.deliveredCount );


	//////////////////////////////////////////////////////////////////////////////////////

	notifier.addNotification( getNotificationTest1(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );
	notifier.addNotification( getNotificationTest2(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );

	notifier.notify( getNotificationTest1() );

	EXPECT_EQ( 5, testClazz.deliveredCount );

	notifier.notify( getNotificationTest2() );
	EXPECT_EQ( 6, testClazz.deliveredCount );

	notifier.removeNotification( &testClazz, getNotificationTest1() );
	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 6, testClazz.deliveredCount );

	notifier.notify( getNotificationTest2() );
	EXPECT_EQ( 7, testClazz.deliveredCount );

	notifier.addNotification( getNotificationTest1(),
							  Utils::makeCallback( &testClazz, &TestClazz::onDeliverNotification ) );
	notifier.notify( getNotificationTest1() );

	EXPECT_EQ( 8, testClazz.deliveredCount );

	notifier.removeAllForObject( &testClazz );

	notifier.notify( getNotificationTest1() );
	EXPECT_EQ( 8, testClazz.deliveredCount );
}
Exemple #5
0
void SelectPoll::notify()
{
    notifier_.notify();
}
Exemple #6
0
int main(){

//	{
//		const std::string mAlign = "xxx,<><,--x";
//		const int mRepeatRow = 1;
//
//		int row = 0;
//		int ibeg=0, iend=0;
//		for(int i=0; i<mAlign.size(); ++i){
//			if(mAlign[i] == ','){
//				++row;
//				
//			}
//		}
//	}

	#define SET4(x, a,b,c,d) x[0]=a; x[1]=b; x[2]=c; x[3]=d
	#define EQ4(x, a,b,c,d) (x[0]==a && x[1]==b && x[2]==c && x[3]==d)

	// Multidimensional data array
	{
	
		// basics
		{
			const int s1=5, s2=4, s3=3, s4=2;
			Data d(Data::INT, s1,s2,s3,s4);

			assert(d.hasData());
			assert(d.type() == Data::INT);
			assert(d.sizeType() == sizeof(int));
			assert(d.isNumerical());
			assert(d.offset() == 0);
			assert(d.order() == 4);
			assert(d.stride() == 1);

			assert(d.size(0) == s1);
			assert(d.size(1) == s2);
			assert(d.size(2) == s3);
			assert(d.size(3) == s4);
			assert(d.size(0,1) == s1*s2);
			assert(d.size(0,1,2) == s1*s2*s3);
			assert(d.size(0,1,2,3) == d.size());
		
			assert(d.indexFlat(0,0,0,0) ==          0);
			assert(d.indexFlat(1,0,0,0) ==          1);
			assert(d.indexFlat(0,1,0,0) ==       s1*1);
			assert(d.indexFlat(0,2,0,0) ==       s1*2);
			assert(d.indexFlat(0,0,1,0) ==    s2*s1*1);
			assert(d.indexFlat(0,0,2,0) ==    s2*s1*2);
			assert(d.indexFlat(0,0,0,1) == s3*s2*s1*1);
			assert(d.indexFlat(0,0,0,2) == s3*s2*s1*2);
			
			for(int i=0; i<d.size(); ++i){
				int i1,i2,i3,i4;
				d.indexDim(i1,i2,i3,i4, i);
				assert(d.inBounds(i1,i2,i3,i4));
				assert(d.indexFlat(i1,i2,i3,i4) == i);
			}
			
			for(int i=0; i<d.size(); ++i) d.assign(i, i);
			for(int i=0; i<d.size(); ++i) assert(d.elem<int>(i) == i);
			
			// resizing
			{
				Data e(Data::INT, 8);
				int N; // resize change, in bytes

				for(int i=0; i<e.size(); ++i) e.assign(i,i);
				
				N=e.resize(16);			assert(e.sizeType()*8==N);
				
				// old elements should be copied over; extras should be zero
				for(int i=0; i<8 ; ++i) assert(e.at<int>(i) == i);
				for(int i=8; i<16; ++i) assert(e.at<int>(i) == 0);

				N=e.resize(0);			assert(e.sizeType()*-16==N);
				N=e.resize(8);			assert(e.sizeType()*  8==N);
				for(int i=0; i<e.size(); ++i) assert(e.at<int>(i) == 0);
			}
			
			// cloning data
			{
				Data e = d;
				assert(e == d);
				
				e.clone();
				assert(d.elems<int>() != e.elems<int>());
				assert(e == d);
			}
			
			// reversed slice
			{				
				Data e = d.reversed();
				for(int i=0; i<e.size(); ++i)
					assert(d.elem<int>(d.size()-1-i) == e.elem<int>(i));

				e.clone();
				for(int i=0; i<e.size(); ++i)
					assert(d.elem<int>(d.size()-1-i) == e.elem<int>(i));
				
				e += d;
				for(int i=0; i<e.size(); ++i)
					assert(e.elem<int>(i) == e.size()-1);
			}
		}


		// reference counting
		{
			Data d1(Data::INT, 4,4);
			assert(Data::references(d1.elems<int>()) == 1);

			{
				Data d2 = d1;
				assert(d1.elems<int>() == d2.elems<int>());
				assert(Data::references(d1.elems<int>()) == 2);
			}
			assert(Data::references(d1.elems<int>()) == 1);

			{
				Data d2 = d1.slice(1);
				Data d3 = d2.slice(1);
				assert(Data::references(d1.elems<int>()) == 3);
			}
			assert(Data::references(d1.elems<int>()) == 1);
		}
		
	
		const float cf = 10;
		float f = 10;
		std::string s = "hello";
		
		Data d(cf);

		assert(d.hasData());
		assert(d.size() == 1);
		assert(d.type() == Data::FLOAT);
		assert(d.at<float>(0) == cf);
		assert(d.toString() == "10");
		assert(d.at<std::string>(0) == "10");
		
//		d.put(std::string("8"));
//		assert(d.at<float>(0) == 8);

		// Getting/setting values
		d.assign(11.f);
		assert(d.at<float>(0) == 11.f);
		
		d.clone();
		assert(d.hasData());
		assert(d.size() == 1);
		assert(d.type() == Data::FLOAT);

		d.assign(11.f);
		assert(d.at<float>(0) == 11.f);

		d.assign(100);
		assert(d.at<float>(0) == 100);
		
		d.set(f);
		assert(d.elems<float>() == &f);
		assert(d.at<float>(0) == f);
		
		d.set(s);
		assert(d.type() == Data::STRING);
		assert(d.size() == 1);
		assert(d.elems<std::string>() == &s);
		assert(d.at<std::string>(0) == s);
		
		d.clone();
		assert(d.elems<std::string>() != &s);
		assert(d.at<std::string>(0) == s);

		d.set("hello");
		assert(d.type() == Data::STRING);
		assert(d.at<std::string>(0) == "hello");

		{
			std::string s = "d2";
			Data d2(s);
			
			d.set("d");
			d2.assign(d);
			assert(d2.at<std::string>(0) == d.at<std::string>(0));
		}
		
		{
			Data a(Data::FLOAT, 3);
			a.assign(10,0);
			a.assign(20,1);
			a.assign(30,2);
			float b[3];
			a.copyTo(b);
			for(int i=0;i<3;++i) assert(b[i] == a.at<float>(i));
		}
		
		// checking elements
		{
			Data::Type types[] = {Data::BOOL, Data::INT, Data::FLOAT, Data::DOUBLE};
			for(int i=0;i<4;++i){
				Data a(types[i], 8);
				a.assignAll(0);
				assert(a.isZero());
				a.assign(1, 1);
				assert(!a.isZero());
				a.assign(1, 3);
				a.assign(1, 5);
				a.assign(1, 7);
				assert(a.slice(0,4,2).isZero());
			}
		}
		
		// searching
		{
			Data e(Data::STRING, 3);
			std::string s1 = "test1", s2 = "test2", s3 = "test3";
			e.assign(s1, 0);
			e.assign(s2, 1);
			e.assign(s3, 2);
			
			assert(e.indexOf(s1) == 0);
			assert(e.indexOf(s2) == 1);
			assert(e.indexOf(s3) == 2);
			assert(e.indexOf(std::string("invalid")) == Data::npos);
		}
		
		// multiple element assignment
		{
			#define ASSERT_EQUALS(a,b,c,d,e)\
				assert(d1.at<int>(0) == a);\
				assert(d1.at<int>(1) == b);\
				assert(d1.at<int>(2) == c);\
				assert(d1.at<int>(3) == d);\
				assert(d1.at<int>(4) == e)

			Data d1(Data::INT, 5);
			d1.assignAll(-1);
			ASSERT_EQUALS(-1,-1,-1,-1,-1);
			
			d1.assignAll(0);
			ASSERT_EQUALS(0,0,0,0,0);
			
			{
				float t[] = {1,2,3,4,5};
				d1.assignFromArray(t,2);
				ASSERT_EQUALS(1,2,0,0,0);
				
				d1.assignFromArray(t+2,2,1,2);
				ASSERT_EQUALS(1,2,3,4,0);
				
				d1.assignAll(0);
				d1.assignFromArray(t,3, 2);
				ASSERT_EQUALS(1,3,5,0,0);
				
				d1.assignFromArray(t+1,2, 2,3);
				ASSERT_EQUALS(1,3,5,2,4);
			}
			#undef ASSERT_EQUALS
		}
	}


	// stringification
	{	//for(int i=0;i<4;++i) printf("%g\n", f4[i]);
		//printf("%s\n", s1.c_str());
		bool b1;
		float f1;
		double d1;
		std::string s1;
		
		bool b4[4];
		float f4[4];
		double d4[4];
		std::string s4[4];
		
		int N;	// number of elements converted

		N=fromToken(f1, "1e-2");		assert(1==N && f1 == float(1e-2));
		N=fromToken(f1, "1000");		assert(1==N && f1 == float(1000));
		N=fromToken(d1, "1e-2");		assert(1==N && d1 == double(1e-2));
		N=fromToken(d1, "1000");		assert(1==N && d1 == double(1000));
		N=fromToken(b1, "0");			assert(1==N && b1 == 0);
		N=fromToken(b1, "1");			assert(1==N && b1 == 1);
		N=fromToken(s1, "\"test\"");	assert(1==N && s1 == "test");
		
		N=fromToken(b4,4,1, "{1,0,1,1}");				assert(4==N && EQ4(b4, 1,0,1,1));
		N=fromToken(b4,4,1, "{0,  1, 0,0}");			assert(4==N && EQ4(b4, 0,1,0,0));
		N=fromToken(f4,4,1, "{1, -1.2, 1e10, +.1}");	assert(4==N && EQ4(f4, 1.f,-1.2f,1e10f,+.1f));
		N=fromToken(d4,4,1, "{1, -1.2, 1e10, +.1}");	assert(4==N && EQ4(d4, 1,-1.2,1e10,+.1));
		N=fromToken(s4,4,1, "{\"one\", \"two\", \"three\", \"four\"}");
														assert(4==N && EQ4(s4, "one","two","three","four"));

		N=toToken(s1, 1000.f);			assert(1==N && s1 == "1000");
		N=toToken(s1, 2000.0);			assert(1==N && s1 == "2000");
		N=toToken(s1, true);			assert(1==N && s1 == "1");
		N=toToken(s1, false);			assert(1==N && s1 == "0");
		N=toToken(s1, "test");			assert(1==N && s1 == "\"test\"");
		N=toToken(s1, std::string("test"));
										assert(1==N && s1 == "\"test\"");		

		SET4(b4, 1,0,1,1);		N=toToken(s1, b4,4,1);	assert(4==N && s1 == "{1, 0, 1, 1}");
		SET4(f4,-1,0.1,3,1e10);	N=toToken(s1, f4,4,1);	assert(4==N && s1 == "{-1, 0.1, 3, 1e+10}");
		SET4(d4,-1,0.1,3,1e10);	N=toToken(s1, d4,4,1);	assert(4==N && s1 == "{-1, 0.1, 3, 1e+10}");
		SET4(s4,"one","two","three","four"); N=toToken(s1,s4,4,1);
														assert(4==N && s1 == "{\"one\", \"two\", \"three\", \"four\"}");
	}


	// test View linked list implementation
	{
		View n00, n10, n11, n20;

		n00.add(n10);
		n00.add(n11);
		n10.add(n20);
		
		// check all of our links
		assert( n00.child == &n10);
		assert(!n00.parent);
		assert(!n00.sibling);
		assert( n10.parent == &n00);
		assert( n10.sibling == &n11);
		assert( n10.child == &n20);
		assert( n11.parent == &n00);
		assert(!n11.child);
		assert(!n11.sibling);
		assert( n20.parent == &n10);
		assert(!n20.child);
		assert(!n20.sibling);
		
		n10.makeLastSibling();
		assert(!n10.sibling);
		assert(n11.sibling == &n10);
		n11.makeLastSibling();

		n10.remove();
		assert(!n10.parent);
		assert(!n10.sibling);
		assert(!n00.child->sibling);
		
		n11.remove();
		assert(!n00.child);

		assert(n10.child == &n20);
	}

	
	// test View memory management
	{
		View * v0d = new View;
		View v1s;
		View * v1d = new View;
		
		assert(v0d->dynamicAlloc());
		assert(!v1s.dynamicAlloc());

		*v0d << v1s << v1d;
		
		delete v0d;
	}



	// Notifications	
	{
		bool bv1=false, bv2=false, bf=false;
		Notifier n;
	
		assert(n.numObservers(Update::Value) == 0);

		n.attach(ntSetBool1, Update::Value, &bv1);
		n.attach(ntSetBool2, Update::Value, &bv2);
		n.attach(ntSetBool1, Update::Focus, &bf);

		assert(n.numObservers(Update::Value) == 2);
		assert(n.numObservers(Update::Focus) == 1);

		n.notify(Update::Value);
		assert(bv1);
		assert(bv2);
		assert(!bf);

		n.notify(Update::Focus);
		assert(bf);
		
		bv1=bv2=false;
		n.detach(ntSetBool1, Update::Value, &bv1);
		n.notify(Update::Value);
		assert(!bv1);
		assert(bv2);

		bv1=bv2=false;
		n.detach(ntSetBool2, Update::Value, &bv2);
		n.notify(Update::Value);
		assert(!bv1);
		assert(!bv2);
	}
	
	{
		bool b=false;
		Button w;
		w.attach(ntValue, Update::Value, &b);
		w.setValue(true);
		assert(b);
		assert(w.getValue() == true);

// Setting to current value should NOT send notification to avoid infinite loops
		b=false;
		w.setValue(w.getValue());
		assert(!b);

// Boolean model variable
		bool v = false;
		w.attachVariable(v);
		w.setValue(true);		assert(v == true);
		w.setValue(false);		assert(v == false);
		
		v = true;
		w.onDataModelSync();		assert(w.getValue() == true);

		w.setValue(true);

		assert(w.data().toToken() == "1");
		w.setValue(false);
		assert(w.data().toToken() == "0");
		w.setDataFromString("0");	assert(w.getValue() == false);
		w.setDataFromString("1");	assert(w.getValue() == true);

		assert(!w.setDataFromString("invalid"));
	}

	{
		Buttons w;
		bool b=false;
		w.attach(ntValue, Update::Value, &b);
		w.setValue(true, 0);
		assert(b);
		assert(w.getValue(0) == true);
		
		w.data().resize(2,2);
		w.data().assignAll(0);

		bool v1 = false;
		bool v2 = false;
		w.attachVariable(v1, 0);
		w.attachVariable(v2, 2);

		w.setValue(true, 0);		assert(v1 == true);
		w.setValue(true, 2);		assert(v2 == true);
		w.setValue(false, 0);		assert(v1 == false);
		w.setValue(false, 2);		assert(v2 == false);

		w.setValue(false, 0);
		w.setValue(false, 1);
		w.setValue(false, 2);
		w.setValue(false, 3);
		assert(w.data().toToken() == "{0, 0, 0, 0}");
		
		v1 = v2 = false;
		w.setDataFromString("{1,1,1,1}");
		assert(w.getValue(0) && w.getValue(1) && w.getValue(2) && w.getValue(3));
		assert(v1 && v2);
	}

	{
		bool b=false;
		Slider w;
		w.attach(ntValue, Update::Value, &b);
		w.setValue(0.99f);
		assert(b);
		assert(w.getValue() == 0.99f);

// Setting to current value should NOT send notification to avoid infinite loops
		b=false;
		w.setValue(w.getValue());
		assert(!b);

		float v;
		w.attachVariable(v);
		w.setValue(0.99);
		assert(v == 0.99f);
		
		v = 0;
		w.onDataModelSync();
		assert(w.getValue() == 0);

		std::string s;
		w.setValue(0.25);
		assert(w.data().toToken() == "0.25");
		w.setDataFromString("0.5");	assert(w.getValue() == 0.5);
									assert(v == 0.5);

		assert(!w.setDataFromString("invalid"));
		assert(w.getValue() == 0.5);
	}

	{
		bool b=false;
		Sliders w(Rect(1), 2,2);
		w.attach(ntValue, Update::Value, &b);
		w.setValue(0.99f, 3);
		assert(b);
		assert(w.getValue(3) == 0.99f);

		float v1, v2;
		w.attachVariable(v1, 0);
		w.attachVariable(v2, 1);

		w.setValue(0.1f, 0); assert(v1 == 0.1f);
		w.setValue(0.2f, 0); assert(v1 == 0.2f);
		
		v1 = 0.8f; v2 = 0.9f;
		w.onDataModelSync();
		assert(w.getValue(0) == 0.8f);
		assert(w.getValue(1) == 0.9f);

		w.setValue(0.1f, 0);
		w.setValue(0.2f, 1);
		w.setValue(0.3f, 2);
		w.setValue(0.4f, 3);
		assert(w.data().toToken() == "{0.1, 0.2, 0.3, 0.4}");
		
		v1=v2=0;
		w.setDataFromString("{0.4,0.3,0.2,0.1}");
		assert(w.getValue(0) == 0.4);
		assert(w.getValue(1) == 0.3);
		assert(w.getValue(2) == 0.2);
		assert(w.getValue(3) == 0.1);
		assert(v1 == (float)w.getValue(0) && v2 == (float)w.getValue(1));
		
//		double vs[4] = {0.11, 0.22, 0.33, 0.44};
//		w.attachVariable(vs,4);
//		w.onDataModelSync();
//		for(int i=0; i<4; ++i) printf("%f\n", w.values()[i]);
//		
//		w.getValue(0.44, 0);
//		w.getValue(0.33, 0);
//		w.getValue(0.22, 0);
//		w.getValue(0.11, 0);
//		for(int i=0; i<4; ++i) printf("%f\n", vs[i]);
	}

	{
		bool b=false;
		Slider2D w;
		w.attach(ntSetBool1, Update::Value, &b);
		w.setValue(0.01f, 0);
		assert(b);
		assert(w.getValue(0) == 0.01f);

// Setting to current value should NOT send notification to avoid infinite loops
		b=false;
		w.setValue(0.01f, 0);
		assert(!b);
		
		b=false;
		w.setValue(0.00f, 0);
		w.setValue(0.01f, 1);
		assert(b);
		assert(w.getValue(1) == 0.01f);
		
		b=false;
		w.setValueMax();
		assert(b);
		assert(w.getValue(0) == 1.f);
		assert(w.getValue(1) == 1.f);
		
		float v1, v2;
		w.attachVariable(v1, 0);
		w.attachVariable(v2, 1);
		
		w.setValue(0.5f, 0);	assert(v1 == 0.5f);
		w.setValue(0.6f, 1);	assert(v2 == 0.6f);
		
		v1 = 0.1;
		v2 = 0.2;
		
		w.onDataModelSync();
		assert(w.getValue(0) == v1);
		assert(w.getValue(1) == v2);
	
		w.setValue(0.2, 0);
		w.setValue(0.3, 1);
		assert(w.data().toToken() == "{0.2, 0.3}");
		
		v1 = v2 = 0;
		w.setDataFromString("{0.7, 0.8}");
		assert(w.getValue(0)==0.7 && w.getValue(1)==0.8);
		assert(v1==(float)w.getValue(0) && v2==(float)w.getValue(1));
	}

	{
		bool b=false;
		SliderGrid<4> w;
		w.attach(ntValue, Update::Value, &b);
		w.setValue(0.01f, 0);
		assert(b);
		assert(w.getValue(0) == 0.01f);

		float v1, v2;
		w.attachVariable(v1, 0);
		w.attachVariable(v2, 1);

		w.setValue(0.1f, 0); assert(v1 == 0.1f);
		w.setValue(0.2f, 0); assert(v1 == 0.2f);
		
		v1 = 0.8f; v2 = 0.9f;
		w.onDataModelSync();
		assert(w.getValue(0) == 0.8f);
		assert(w.getValue(1) == 0.9f);

		w.setValue(0.1f, 0);
		w.setValue(0.2f, 1);
		w.setValue(0.3f, 2);
		w.setValue(0.4f, 3);
		assert(w.data().toToken() == "{0.1, 0.2, 0.3, 0.4}");
		
		v1=v2=0;
		w.setDataFromString("{0.4,0.3,0.2,0.1}");
		assert(w.getValue(0) == 0.4);
		assert(w.getValue(1) == 0.3);
		assert(w.getValue(2) == 0.2);
		assert(w.getValue(3) == 0.1);
		assert(v1 == (float)w.getValue(0) && v2 == (float)w.getValue(1));
	}
	
	{
		bool b=false;
		SliderRange w;
		w.attach(ntValue, Update::Value, &b);
		w.setValue(0.01f, 0);
		w.setValue(0.02f, 1);
		assert(b);
		assert(w.getValue(0) == 0.01f);
		assert(w.getValue(1) == 0.02f);
		assert(w.center() == 0.015f);
		assert(w.range() == 0.01f);
		
		w.endpoints(0,1);
		assert(w.getValue(0) == 0);
		assert(w.getValue(1) == 1);
		
		w.centerRange(0.5, 0.25);
		assert(w.getValue(0) == (0.5-0.25/2));
		assert(w.getValue(1) == (0.5+0.25/2));

		float v1,v2;
		w.attachVariable(v1, 0);
		w.attachVariable(v2, 1);

		w.setValue(0.2, 0);
		w.setValue(0.3, 1);
		assert(w.data().toToken() == "{0.2, 0.3}");
		
		v1 = v2 = 0;
		w.setDataFromString("{0.7, 0.8}");
		assert(w.getValue(0)==0.7 && w.getValue(1)==0.8);
		assert(v1==(float)w.getValue(0) && v2==(float)w.getValue(1));
	}

	{
		bool b=false;
		Label w;

		w.attach(ntValue, Update::Value, &b);
		w.setValue("test");
		assert(b);
		assert(w.getValue() == "test");
		
		assert(w.data().toToken() == "\"test\"");
		
		w.setValue("");
		w.setDataFromString("\"test\"");	assert(w.getValue() == "test");
	}

	{

//		{
//			double val = 1e14;
//			double inc = 1;
//			printf("%f\n", val + inc*1);
//			printf("%f\n", val + inc*2);
//			printf("%f\n", val + inc*3);
//			printf("%f\n", val + inc*4);
//		}

		bool b=false;
		NumberDialer w(1,2,1,0);
		w.attach(ntValue, Update::Value, &b);
		w.setValue(0.75);
		assert(b);
		assert(w.getValue() == 0.75);

// Setting to current value should NOT send notification to avoid infinite loops
		b=false;
		w.setValue(w.getValue());
		assert(!b);

		double v=0;
		w.attachVariable(v);
		w.setValue(0.5);	assert(v == 0.5);
		
		v = 0.25;
		w.onDataModelSync();
		assert(w.getValue() == v);

		w.setValue(0.2);
		assert(w.data().toToken() == "0.2");
		
		v = 0;
		w.setDataFromString("0.8");
		assert(w.getValue()==0.8 && w.getValue()==v);
	}

	{
		bool b=false;
		TextView w;
		w.attach(ntValue, Update::Value, &b);
		w.setValue("hello");
		assert(b);
		assert(w.getValue() == "hello");
		
		assert(w.data().toToken() == "\"hello\"");

		std::string v = "test";
		w.attachVariable(v);
		
		w.onDataModelSync();
		assert(w.getValue() == "test");

		w.setDataFromString("\"world\"");
		assert(w.getValue() == "world");
		assert(v == "world");
	}



	// model to string conversion
	{
		Label l;
		TextView tv;
		Button b;
		Buttons bs(Rect(), 2, 2);
		Slider s;
		Sliders ss(Rect(), 1, 4);
		Slider2D s2D;
		NumberDialer nd(1,4,1,-1);
		std::string strings[] = {"test1", "test2", "test3"};
	
		l.setValue("Hello Label!").name("l");
		tv.setValue("Hello TextView!").name("tv");
		b.setValue(true).name("b");
		bs.setValue(true, 0,1).name("bs");
		s.setValue(0.5).name("s");
		ss.setValue(0.4, 1).name("ss");
		s2D.setValue(0.5, 0).setValue(0.1, 1).name("s2D");
		nd.setValue(-0.54941).name("nd");

		const View * views[] = {&l, &tv, &b, &bs, &s, &ss, &s2D, &nd};
		for(unsigned i=0; i<sizeof(views)/sizeof(View *); ++i){
			//const Data& d = views[i]->data();
			//printf("%p: %s\n", &d, d.toString().c_str());
			//views[i]->model().print(); printf("\n");
		}

		View top;
		top << l << tv << b << bs << s << ss << s2D << nd;
	
		std::string str1, str2;
//		top.modelToString(str1, "test model");		
//		printf("%s\n", str1.c_str());
//
//		l.setValue("changed...");
//		top.modelFromString(str1);
//		top.modelToString(str2);
//		printf("%s\n", str2.c_str());
//		assert(str1 == str2);

		ModelManager mm;
		
		mm.add("l", l);
		mm.add("tv", tv);
		mm.add("b", b);
		mm.add("bs", bs);
		mm.add("s" , s);
		mm.add("ss", ss);
		mm.add("s2D",s2D);
		mm.add("nd", nd);
		
		Data dat(strings, 3);
		//Data dat(10);
		//dat.print();
		//mm.add("strings", dat);
		//mm.add("strings", *new Data(strings, 3));
		
//		mm.toToken(str1, "test");
//		printf("%s\n", str1.c_str());
//		
//		mm.fromToken(str1);
//		mm.toToken(str2, "test");
//		printf("%s\n", str2.c_str());

		std::string snapshotString1 =
"[\"test 1\"] = {\n\
	l = \"Label 1\",\n\
	tv = \"TextView 1\",\n\
	b = 0,\n\
	bs = {0,0,0,0},\n\
}";

		std::string snapshotString2 =
"[\"test 2\"] = {\n\
	l = \"Label 2\",\n\
	tv = \"TextView 2\",\n\
	b = 1,\n\
	bs = {1,1,1,1},\n\
	s = 1,\n\
	ss = {1,1,1,1},\n\
	s2D = {1,1},\n\
	nd = 1,\n\
}";
		
		mm.snapshotsFromString("{" + snapshotString1 + ",\r\n" + snapshotString2 + "}");

//		mm.snapshots()["test 1"]["l"].print();
//		mm.snapshots()["test 1"]["b"].print();
//		mm.snapshots()["test 1"]["bs"].print();
//		mm.snapshots()["test 1"]["s"].print();
//		mm.snapshots()["test 1"]["ss"].print();
//		mm.snapshots()["test 1"]["s2D"].print();
//		mm.snapshots()["test 1"]["nd"].print();
//		mm.snapshots()["test 2"]["l"].print();
//		mm.snapshots()["test 2"]["b"].print();
//		mm.snapshots()["test 2"]["bs"].print();
//		mm.snapshots()["test 2"]["s"].print();
//		mm.snapshots()["test 2"]["ss"].print();
//		mm.snapshots()["test 2"]["s2D"].print();
//		mm.snapshots()["test 2"]["nd"].print();
//
//		mm.snapshotsToFile("snapshots.txt");
//		
//		mm.clearSnapshots();
//		mm.snapshotsFromFile("snapshots.txt");
//
//		str1.clear();
//		mm.snapshotsToString(str1);
//		printf("%s\n", str1.c_str());
	}

//	{
//		std::string str( "a bc ab ca ab" );
//		std::string searchString("ab"); 
//		std::string replaceString("hello");
//
//		std::string::size_type pos = 0;
//		while((pos = str.find(searchString, pos)) != std::string::npos){
//			str.replace(pos++, searchString.size(), replaceString);
//		}
//		printf("%s\n", str.c_str());
//	}

//	printf("sizeof(Notifier): %d\n", sizeof(Notifier));
//	printf("sizeof(View): %d\n", sizeof(View));
//	printf("sizeof(Data): %d\n", sizeof(Data));
//	printf("sizeof(Model): %d\n", sizeof(Model));
//	printf("sizeof(ModelManager): %d\n", sizeof(ModelManager));

	return 0;
}
Exemple #7
0
void EPoll::notify()
{
    notifier_.notify();
}