View | Details | Raw Unified | Return to bug 474634
Collapse All | Expand All

(-)UIAutomationWinforms/Mono.UIAutomation.Winforms/FragmentControlProvider.cs (-41 / +132 lines)
Lines 43-48 Link Here
43
		#region Private Fields
43
		#region Private Fields
44
		
44
		
45
		private List<FragmentControlProvider> children;
45
		private List<FragmentControlProvider> children;
46
		private List<Component> componentChildren;
46
		private INavigation navigation;
47
		private INavigation navigation;
47
		private SWF.ContextMenu contextMenu;
48
		private SWF.ContextMenu contextMenu;
48
		private SWF.ContextMenuStrip contextMenuStrip;
49
		private SWF.ContextMenuStrip contextMenuStrip;
Lines 63-68 Link Here
63
			componentProviders =
64
			componentProviders =
64
				new Dictionary<Component, FragmentControlProvider> ();
65
				new Dictionary<Component, FragmentControlProvider> ();
65
			children = new List<FragmentControlProvider> ();
66
			children = new List<FragmentControlProvider> ();
67
			componentChildren = new List<Component> ();
66
68
67
			if (Control != null) {
69
			if (Control != null) {
68
				Control.ContextMenuChanged += HandleContextMenuChanged;
70
				Control.ContextMenuChanged += HandleContextMenuChanged;
Lines 223-252 Link Here
223
			//       aren't sent to bridge until the parent's already
225
			//       aren't sent to bridge until the parent's already
224
			//       there.  There are about 100 ways to do this
226
			//       there.  There are about 100 ways to do this
225
			//       better.
227
			//       better.
226
			if (Control != null) {
228
			if (Control != null) {				
227
				Control.ControlAdded += OnControlAdded;
229
				Control.ControlAdded += OnControlAdded;
228
				Control.ControlRemoved += OnControlRemoved;
230
				Control.ControlRemoved += OnControlRemoved;
229
				
231
				
230
				foreach (SWF.Control childControl in Control.Controls) {
232
				foreach (SWF.Control childControl in Control.Controls)
231
					FragmentControlProvider childProvider =
233
					HandleComponentAdded (childControl, false);
232
						CreateProvider (childControl);
233
					
234
					if (childProvider == null)
235
						continue;
236
					// TODO: Null check, compound, etc?
237
238
					componentProviders [childControl] = childProvider;
239
					OnNavigationChildAdded (false,
240
					                        (FragmentControlProvider) childProvider);
241
				}
242
			}
234
			}
243
		}
235
		}
244
		
236
		
245
		public virtual void FinalizeChildControlStructure ()
237
		public virtual void FinalizeChildControlStructure ()
246
		{
238
		{
247
			for (; children.Count > 0; )
239
			for (; componentChildren.Count > 0; )
248
				OnNavigationChildRemoved (false, 
240
				HandleComponentRemoved (componentChildren [0], false);
249
				                          (FragmentControlProvider) children [0]);
250
241
251
			children.Clear ();
242
			children.Clear ();
252
			componentProviders.Clear ();
243
			componentProviders.Clear ();
Lines 320-356 Link Here
320
	
311
	
321
		private void OnControlAdded (object sender, SWF.ControlEventArgs args)
312
		private void OnControlAdded (object sender, SWF.ControlEventArgs args)
322
		{
313
		{
323
			SWF.Control childControl = args.Control;
314
			HandleComponentAdded (args.Control, true);
324
			FragmentControlProvider childProvider = CreateProvider (childControl);
325
			if (childProvider == null)
326
				return;
327
328
			componentProviders [childControl] = childProvider;	
329
			OnNavigationChildAdded (true, 
330
			                        (FragmentControlProvider) childProvider);
331
		}
315
		}
332
	
316
	
333
		private void OnControlRemoved (object sender, SWF.ControlEventArgs args)
317
		private void OnControlRemoved (object sender, SWF.ControlEventArgs args)
334
		{
318
		{
335
			FragmentControlProvider removedProvider;
319
			HandleComponentRemoved (args.Control, true);
336
			
337
			if (componentProviders.TryGetValue (args.Control, out removedProvider) == true) {
338
				
339
				// TODO: Some sort of disposal
340
				
341
				componentProviders.Remove (args.Control);
342
				// StructureChangedEvent
343
				// TODO: Use correct arguments, and fix bridge
344
				//       to handle them!!!
345
				//       Event source: Parent of removed child
346
				//       runtimeId: The child that was removed.
347
				//       (pg 6 of fxref_uiautomationtypes_p2.pdf)
348
				OnNavigationChildRemoved (true, 
349
				                          (FragmentControlProvider) removedProvider);
350
				ProviderFactory.ReleaseProvider (args.Control);
351
			}
352
		}
320
		}
353
321
322
		private void OnNotVisibleControlVisibleChanged (object sender, EventArgs args)
323
		{
324
			SWF.Control control = (SWF.Control) sender;
325
326
			if (control.Visible)
327
				InitializeComponentProvider (control, true);
328
			else
329
				TerminateComponentProvider (control, true);
330
		}
331
354
		#endregion
332
		#endregion
355
333
356
		#region Protected Methods
334
		#region Protected Methods
Lines 362-367 Link Here
362
340
363
			return (FragmentControlProvider) ProviderFactory.GetProvider (control);
341
			return (FragmentControlProvider) ProviderFactory.GetProvider (control);
364
		}
342
		}
343
344
		protected virtual FragmentControlProvider CreateProvider (Component component)
345
		{
346
			return (FragmentControlProvider) ProviderFactory.GetProvider (component);
347
		}
348
349
		protected virtual void DestroyProvider (Component component)
350
		{
351
			ProviderFactory.ReleaseProvider (component);
352
		}
365
		
353
		
366
		protected FragmentControlProvider GetProvider (SWF.Control control)
354
		protected FragmentControlProvider GetProvider (SWF.Control control)
367
		{
355
		{
Lines 371-377 Link Here
371
				return null;
359
				return null;
372
		}
360
		}
373
361
362
		protected void InitializeComponentProvider (Component childComponent,
363
		                                            bool raiseEvent)
364
		{
365
			SWF.Control control = null;
366
			FragmentControlProvider childProvider = null;
367
			
368
			if ((control = childComponent as SWF.Control) != null)
369
				childProvider = CreateProvider (control);
370
			else
371
				childProvider = CreateProvider (childComponent);
372
			
373
			if (childProvider == null)
374
				return;
375
			// TODO: Null check, compound, etc?
376
377
			componentProviders [childComponent] = childProvider;
378
			OnNavigationChildAdded (raiseEvent, childProvider);
379
		}
380
381
		protected void TerminateComponentProvider (Component childComponent,
382
		                                           bool raiseEvent)
383
		{			
384
			FragmentControlProvider removedProvider;
385
			
386
			if (componentProviders.TryGetValue (childComponent, 
387
			                                    out removedProvider)) {
388
				componentProviders.Remove (childComponent);
389
				// Event source:
390
				//       Parent of removed child runtimeId: The child that was
391
				//       removed. (pg 6 of fxref_uiautomationtypes_p2.pdf)
392
				OnNavigationChildRemoved (raiseEvent, removedProvider);
393
				DestroyProvider (childComponent);
394
			}
395
		}
396
397
		protected void AddChildComponent (Component childComponent)
398
		{
399
			if (componentChildren.Contains (childComponent))
400
				return;
401
402
			componentChildren.Add (childComponent);
403
			AddVisibleEvent (childComponent);
404
		}
405
406
		protected void RemoveChildComponent (Component childComponent)
407
		{
408
			if (!componentChildren.Contains (childComponent))
409
				return;
410
			
411
			componentChildren.Remove (childComponent);
412
			RemoveVisibleEvent (childComponent);
413
		}
414
415
		protected virtual void AddVisibleEvent (Component component)
416
		{
417
			SWF.Control control = null;
418
419
			if ((control = component as SWF.Control) != null)
420
				control.VisibleChanged += OnNotVisibleControlVisibleChanged;
421
		}		
422
423
		protected virtual void RemoveVisibleEvent (Component component)
424
		{
425
			SWF.Control control = null;
426
427
			if ((control = component as SWF.Control) != null)
428
				control.VisibleChanged -= OnNotVisibleControlVisibleChanged;			
429
		}
430
431
		protected virtual bool IsComponentVisible (Component component)
432
		{
433
			SWF.Control control = null;
434
			if ((control = component as SWF.Control) != null)
435
				return control.Visible;
436
			else // Component based providers will need to override this method
437
				return false;
438
		}
439
374
		#endregion
440
		#endregion
441
442
		#region Private Methods
443
444
		private void HandleComponentAdded (Component component, bool raiseEvent)
445
		{
446
			AddChildComponent (component);
447
448
			// We don't add an invisible component but we keep track of its 
449
			// Visible event to add it when Visible changes
450
			if (!IsComponentVisible (component))
451
				return;
452
453
			InitializeComponentProvider (component, raiseEvent);
454
		}
455
456
		private void HandleComponentRemoved (Component component, bool raiseEvent)
457
		{
458
			// We will only need to Terminate when is visible.
459
			if (IsComponentVisible (component))
460
				TerminateComponentProvider (component, raiseEvent);
461
462
			RemoveChildComponent (component);
463
		}
464
465
		#endregion
375
		
466
		
376
		#region IRawElementProviderFragment Interface 
467
		#region IRawElementProviderFragment Interface 
377
468
(-)UIAutomationWinformsTests/FormProviderTest.cs (+166 lines)
Lines 825-830 Link Here
825
		}
825
		}
826
826
827
#endregion
827
#endregion
828
829
		#region Invisible/Visible Tests
830
831
		[Test]
832
		public void InvisibleVisibleTest ()
833
		{
834
			IRawElementProviderFragmentRoot rootProvider = null;
835
			IRawElementProviderFragment buttonProvider = null;
836
			Button button = null;
837
			Form f = null;
838
			
839
			// Exposes 474634 and 464356
840
			using (f = new Form ()) {
841
				f.Size = new System.Drawing.Size (400, 400);
842
				f.Show ();
843
844
				// Empty form NO CHILDREN
845
				rootProvider 
846
					= (IRawElementProviderFragmentRoot) ProviderFactory.GetProvider (f);
847
848
				Assert.AreEqual (0, 
849
				                 ChildrenCount (rootProvider),
850
				                 "No children");
851
852
				// Adding invisible button
853
				button = new Button ();
854
				button.Text = "button";
855
				button.Visible = false;
856
				f.Controls.Add (button);
857
858
				Assert.AreEqual (0, 
859
				                 ChildrenCount (rootProvider),
860
				                 "No children");
861
862
				// Changing visibility
863
				bridge.ResetEventLists ();
864
				button.Visible = true;
865
				Assert.AreEqual (1, 
866
				                 ChildrenCount (rootProvider),
867
				                 "1 child");
868
				buttonProvider
869
					= (IRawElementProviderFragment) ProviderFactory.FindProvider (button);
870
				Assert.IsNotNull (buttonProvider, "ButtonProvider missing");
871
				Assert.IsNotNull (bridge.GetStructureChangedEventFrom (buttonProvider,
872
				                                                       StructureChangeType.ChildAdded),
873
				                  "Button. StructureChangeType.ChildAdded event missing");
874
				Assert.AreEqual (rootProvider,
875
				                 buttonProvider.Navigate (NavigateDirection.Parent),
876
				                 "FormProvider != button.Parent");
877
				buttonProvider = null;
878
				
879
				bridge.ResetEventLists ();
880
				button.Visible = false;
881
				Assert.AreEqual (0, 
882
				                 ChildrenCount (rootProvider),
883
				                 "1 child");
884
				buttonProvider
885
					= (IRawElementProviderFragment) ProviderFactory.FindProvider (button);
886
				Assert.IsNull (buttonProvider, "ButtonProvider missing");
887
				Assert.IsNull (bridge.GetStructureChangedEventFrom (buttonProvider,
888
				                                                    StructureChangeType.ChildAdded),
889
				               "Button. StructureChangeType.ChildAdded event missing");
890
				buttonProvider = null;
891
892
				// We are already invisible, we don't need to raise any event
893
				bridge.ResetEventLists ();
894
				f.Controls.Remove (button);
895
				Assert.AreEqual (0,
896
				                 ChildrenCount (rootProvider),
897
				                 "No children");
898
				buttonProvider
899
					= (IRawElementProviderFragment) ProviderFactory.FindProvider (button);
900
				Assert.IsNull (buttonProvider, "ButtonProvider missing");
901
				Assert.IsNull (bridge.GetStructureChangedEventFrom (buttonProvider,
902
				                                                    StructureChangeType.ChildAdded),
903
				               "Button. StructureChangeType.ChildAdded event missing");
904
			}
905
		}
906
907
		[Test]
908
		public void InvisibleVisibleTest1 ()
909
		{
910
			// Similar to InvisibleVisibleTest but with invisible items
911
			// before calling Show and getting the provider.
912
			IRawElementProviderFragmentRoot rootProvider = null;
913
			IRawElementProviderSimple buttonProvider = null;
914
			Button button = null;
915
			
916
			Form f = new Form ();
917
			f.Size = new System.Drawing.Size (400, 400);
918
			f.Show ();
919
920
			// Adding invisible button
921
			button = new Button ();
922
			button.Text = "button";
923
			button.Visible = false;
924
			f.Controls.Add (button);
925
926
			f.Show ();
927
928
			// Empty form NO CHILDREN
929
			rootProvider 
930
				= (IRawElementProviderFragmentRoot) ProviderFactory.GetProvider (f);
931
932
			Assert.AreEqual (0, 
933
			                 ChildrenCount (rootProvider),
934
			                 "No children");
935
936
			// Changing visibility
937
			bridge.ResetEventLists ();
938
			button.Visible = true;
939
			Assert.AreEqual (1, 
940
			                 ChildrenCount (rootProvider),
941
			                 "1 child");
942
			buttonProvider
943
				= ProviderFactory.FindProvider (button);
944
			Assert.IsNotNull (buttonProvider, "ButtonProvider missing");
945
			Assert.IsNotNull (bridge.GetStructureChangedEventFrom (buttonProvider,
946
			                                                       StructureChangeType.ChildAdded),
947
			                  "Button. StructureChangeType.ChildAdded event missing");
948
			buttonProvider = null;
949
			
950
			bridge.ResetEventLists ();
951
			button.Visible = false;
952
			Assert.AreEqual (0, 
953
			                 ChildrenCount (rootProvider),
954
			                 "1 child");
955
			buttonProvider
956
				= ProviderFactory.FindProvider (button);
957
			Assert.IsNull (buttonProvider, "ButtonProvider missing");
958
			Assert.IsNull (bridge.GetStructureChangedEventFrom (buttonProvider,
959
			                                                    StructureChangeType.ChildAdded),
960
			               "Button. StructureChangeType.ChildAdded event missing");
961
			buttonProvider = null;
962
963
			// We are already invisible, we don't need to raise any event
964
			bridge.ResetEventLists ();
965
			f.Controls.Remove (button);
966
			Assert.AreEqual (0,
967
			                 ChildrenCount (rootProvider),
968
			                 "No children");
969
			buttonProvider
970
				= ProviderFactory.FindProvider (button);
971
			Assert.IsNull (buttonProvider, "ButtonProvider missing");
972
			Assert.IsNull (bridge.GetStructureChangedEventFrom (buttonProvider,
973
			                                                    StructureChangeType.ChildAdded),
974
			               "Button. StructureChangeType.ChildAdded event missing");
975
976
			f.Dispose ();
977
		}
978
979
		private int ChildrenCount (IRawElementProviderFragmentRoot rootProvider)
980
		{
981
			int children = 0;
982
			
983
			IRawElementProviderFragment child 
984
				= rootProvider.Navigate (NavigateDirection.FirstChild);
985
			while (child != null) {
986
				children++;
987
				child = child.Navigate (NavigateDirection.NextSibling);
988
			}
989
990
			return children;
991
		}
992
993
		#endregion
828
		
994
		
829
#region BaseProviderTest Overrides
995
#region BaseProviderTest Overrides
830
		
996
		

Return to bug 474634