<commit_before>// 
// ViewBackend.cs
//  
// Author:
//       <NAME> <<EMAIL>>
// 
// Copyright (c) 2011 Xamarin Inc
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Xml;
using MonoMac.AppKit;
using MonoMac.Foundation;
using MonoMac.ObjCRuntime;
using Xwt;
using Xwt.Backends;


namespace Xwt.Mac
{
	public abstract class ViewBackend<T,S>: ViewBackend where T:NSView where S:IWidgetEventSink
	{
		public new S EventSink {
			get { return (S) base.EventSink; }
		}
		
		public new T Widget {
			get { return (T) base.Widget; }
		}
	}

	public abstract class ViewBackend: IWidgetBackend
	{
		Widget frontend;
		IWidgetEventSink eventSink;
		IViewObject viewObject;
		WidgetEvent currentEvents;
		bool autosize;
		Size lastFittingSize;
		bool sensitive = true;
		bool canGetFocus = true;

		void IBackend.InitializeBackend (object frontend, ApplicationContext context)
		{
			ApplicationContext = context;
			this.frontend = (Widget) frontend;
		}
		
		void IWidgetBackend.Initialize (IWidgetEventSink sink)
		{
			eventSink = (IWidgetEventSink) sink;
			Initialize ();
			ResetFittingSize ();
			canGetFocus = Widget.AcceptsFirstResponder ();
		}

		// To be called when the widget is a root and is not inside a Xwt window. For example, when it is in a popover or a tooltip
		// In that case, the widget has to listen to the change event of the children and resize itself
		public void SetAutosizeMode (bool autosize)
		{
			this.autosize = autosize;
			if (autosize)
				AutoUpdateSize ();
		}

		
		public virtual void Initialize ()
		{
		}
		
		public IWidgetEventSink EventSink {
			get { return eventSink; }
		}
		
		public Widget Frontend {
			get {
				return this.frontend;
			}
		}
		
		public ApplicationContext ApplicationContext {
			get;
			private set;
		}
		
		public object NativeWidget {
			get {
				return Widget;
			}
		}
		
		public NSView Widget {
			get { return (NSView) ViewObject.View; }
		}
		
		public IViewObject ViewObject {
			get { return viewObject; }
			set {
				viewObject = value;
				viewObject.Backend = this;
			}
		}
		
		public bool Visible {
			get { return !Widget.Hidden; }
			set { Widget.Hidden = !value; }
		}
		
		public virtual bool Sensitive {
			get { return sensitive; }
			set {
				sensitive = value;
				UpdateSensitiveStatus (Widget, sensitive && ParentIsSensitive ());
			}
		}

		bool ParentIsSensitive ()
		{
			IViewObject parent = Widget.Superview as IViewObject;
			if (parent == null) {
				var wb = Widget.Window as WindowBackend;
				return wb == null || wb.Sensitive;
			}
			if (!parent.Backend.Sensitive)
				return false;
			return parent.Backend.ParentIsSensitive ();
		}

		internal void UpdateSensitiveStatus (NSView view, bool parentIsSensitive)
		{
			if (view is NSControl)
				((NSControl)view).Enabled = parentIsSensitive && sensitive;

			foreach (var s in view.Subviews) {
				if (s is IViewObject)
					((IViewObject)s).Backend.UpdateSensitiveStatus (s, parentIsSensitive);
				else
					UpdateSensitiveStatus (s, sensitive && parentIsSensitive);
			}
		}

		public virtual bool CanGetFocus {
			get { return canGetFocus; }
			set {
				canGetFocus = value;
				if (!Widget.AcceptsFirstResponder ())
					canGetFocus = false;
			}
		}
		
		public virtual bool HasFocus {
			get {
				return Widget.Window != null && Widget.Window.FirstResponder == Widget;
			}
		}
		
		public virtual void SetFocus ()
		{
			if (Widget.Window != null && CanGetFocus)
				Widget.Window.MakeFirstResponder (Widget);
		}
		
		public string TooltipText {
			get {
				return Widget.ToolTip;
			}
			set {
				Widget.ToolTip = value;
			}
		}
		
		public void NotifyPreferredSizeChanged ()
		{
			EventSink.OnPreferredSizeChanged ();
		}
		
		public void SetCursor (CursorType cursor)
		{
			NSCursor ctype;
			if (cursor == CursorType.Arrow)
				ctype = NSCursor.ArrowCursor;
			else if (cursor == CursorType.Crosshair)
				ctype = NSCursor.CrosshairCursor;
			else if (cursor == CursorType.Hand)
				ctype = NSCursor.ClosedHandCursor;
			else if (cursor == CursorType.IBeam)
				ctype = NSCursor.IBeamCursor;
			else if (cursor == CursorType.ResizeDown)
				ctype = NSCursor.ResizeDownCursor;
			else if (cursor == CursorType.ResizeUp)
				ctype = NSCursor.ResizeUpCursor;
			else if (cursor == CursorType.ResizeLeft)
				ctype = NSCursor.ResizeLeftCursor;
			else if (cursor == CursorType.ResizeRight)
				ctype = NSCursor.ResizeRightCursor;
			else if (cursor == CursorType.ResizeLeftRight)
				ctype = NSCursor.ResizeLeftRightCursor;
			else if (cursor == CursorType.ResizeUpDown)
				ctype = NSCursor.ResizeUpDownCursor;
			else
				ctype = NSCursor.ArrowCursor;
			// TODO: assign the cursor
		}
		
		~ViewBackend ()
		{
			Dispose (false);
		}
		
		public void Dispose ()
		{
			GC.SuppressFinalize (this);
			Dispose (true);
		}
		
		protected virtual void Dispose (bool disposing)
		{
		}
		
		public virtual SizeRequestMode SizeRequestMode {
			get { return SizeRequestMode.HeightForWidth; }
		}
		
		Size IWidgetBackend.Size {
			get { return new Size (Widget.WidgetWidth () - Frontend.Margin.HorizontalSpacing, Widget.WidgetHeight () - Frontend.Margin.VerticalSpacing); }
		}
		
		public static NSView GetWidget (IWidgetBackend w)
		{
			return ((ViewBackend)w).Widget;
		}

		public static NSView GetWidget (Widget w)
		{
			return GetWidget ((IWidgetBackend)Toolkit.GetBackend (w));
		}
		
		public virtual object Font {
			get {
				if (Widget is NSControl)
					return ((NSControl)(object)Widget).Font;
				if (Widget is NSText)
					return ((NSText)(object)Widget).Font;
				return NSFont.ControlContentFontOfSize (NSFont.SystemFontSize);
			}
			set {
				if (Widget is NSControl)
					((NSControl)(object)Widget).Font = (NSFont) value;
				if (Widget is NSText)
					((NSText)(object)Widget).Font = (NSFont) value;
			}
		}
		
		public virtual Xwt.Drawing.Color BackgroundColor {
			get;
			set;
		}
		
		#region IWidgetBackend implementation
		
		public Point ConvertToScreenCoordinates (Point widgetCoordinates)
		{
			var lo = Widget.ConvertPointToBase (new PointF ((float)widgetCoordinates.X, (float)widgetCoordinates.Y));
			lo = Widget.Window.ConvertBaseToScreen (lo);
			return MacDesktopBackend.ToDesktopRect (new RectangleF (lo.X, lo.Y, 0, Widget.IsFlipped ? 0 : Widget.Frame.Height)).Location;
		}
		
		protected virtual Size GetNaturalSize ()
		{
//			var s = Widget.FittingSize;
//			return new Size (s.Width, s.Height);
			return lastFittingSize;
		}

		public virtual WidgetSize GetPreferredWidth ()
		{
			var w = GetNaturalSize ().Width;<commit_msg>[Mac] Fix sizing issue when changing the font of a widget<commit_after>// 
// ViewBackend.cs
//  
// Author:
//       <NAME> <<EMAIL>>
// 
// Copyright (c) 2011 Xamarin Inc
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Xml;
using MonoMac.AppKit;
using MonoMac.Foundation;
using MonoMac.ObjCRuntime;
using Xwt;
using Xwt.Backends;


namespace Xwt.Mac
{
	public abstract class ViewBackend<T,S>: ViewBackend where T:NSView where S:IWidgetEventSink
	{
		public new S EventSink {
			get { return (S) base.EventSink; }
		}
		
		public new T Widget {
			get { return (T) base.Widget; }
		}
	}

	public abstract class ViewBackend: IWidgetBackend
	{
		Widget frontend;
		IWidgetEventSink eventSink;
		IViewObject viewObject;
		WidgetEvent currentEvents;
		bool autosize;
		Size lastFittingSize;
		bool sensitive = true;
		bool canGetFocus = true;

		void IBackend.InitializeBackend (object frontend, ApplicationContext context)
		{
			ApplicationContext = context;
			this.frontend = (Widget) frontend;
		}
		
		void IWidgetBackend.Initialize (IWidgetEventSink sink)
		{
			eventSink = (IWidgetEventSink) sink;
			Initialize ();
			ResetFittingSize ();
			canGetFocus = Widget.AcceptsFirstResponder ();
		}

		// To be called when the widget is a root and is not inside a Xwt window. For example, when it is in a popover or a tooltip
		// In that case, the widget has to listen to the change event of the children and resize itself
		public void SetAutosizeMode (bool autosize)
		{
			this.autosize = autosize;
			if (autosize)
				AutoUpdateSize ();
		}

		
		public virtual void Initialize ()
		{
		}
		
		public IWidgetEventSink EventSink {
			get { return eventSink; }
		}
		
		public Widget Frontend {
			get {
				return this.frontend;
			}
		}
		
		public ApplicationContext ApplicationContext {
			get;
			private set;
		}
		
		public object NativeWidget {
			get {
				return Widget;
			}
		}
		
		public NSView Widget {
			get { return (NSView) ViewObject.View; }
		}
		
		public IViewObject ViewObject {
			get { return viewObject; }
			set {
				viewObject = value;
				viewObject.Backend = this;
			}
		}
		
		public bool Visible {
			get { return !Widget.Hidden; }
			set { Widget.Hidden = !value; }
		}
		
		public virtual bool Sensitive {
			get { return sensitive; }
			set {
				sensitive = value;
				UpdateSensitiveStatus (Widget, sensitive && ParentIsSensitive ());
			}
		}

		bool ParentIsSensitive ()
		{
			IViewObject parent = Widget.Superview as IViewObject;
			if (parent == null) {
				var wb = Widget.Window as WindowBackend;
				return wb == null || wb.Sensitive;
			}
			if (!parent.Backend.Sensitive)
				return false;
			return parent.Backend.ParentIsSensitive ();
		}

		internal void UpdateSensitiveStatus (NSView view, bool parentIsSensitive)
		{
			if (view is NSControl)
				((NSControl)view).Enabled = parentIsSensitive && sensitive;

			foreach (var s in view.Subviews) {
				if (s is IViewObject)
					((IViewObject)s).Backend.UpdateSensitiveStatus (s, parentIsSensitive);
				else
					UpdateSensitiveStatus (s, sensitive && parentIsSensitive);
			}
		}

		public virtual bool CanGetFocus {
			get { return canGetFocus; }
			set {
				canGetFocus = value;
				if (!Widget.AcceptsFirstResponder ())
					canGetFocus = false;
			}
		}
		
		public virtual bool HasFocus {
			get {
				return Widget.Window != null && Widget.Window.FirstResponder == Widget;
			}
		}
		
		public virtual void SetFocus ()
		{
			if (Widget.Window != null && CanGetFocus)
				Widget.Window.MakeFirstResponder (Widget);
		}
		
		public string TooltipText {
			get {
				return Widget.ToolTip;
			}
			set {
				Widget.ToolTip = value;
			}
		}
		
		public void NotifyPreferredSizeChanged ()
		{
			EventSink.OnPreferredSizeChanged ();
		}
		
		public void SetCursor (CursorType cursor)
		{
			NSCursor ctype;
			if (cursor == CursorType.Arrow)
				ctype = NSCursor.ArrowCursor;
			else if (cursor == CursorType.Crosshair)
				ctype = NSCursor.CrosshairCursor;
			else if (cursor == CursorType.Hand)
				ctype = NSCursor.ClosedHandCursor;
			else if (cursor == CursorType.IBeam)
				ctype = NSCursor.IBeamCursor;
			else if (cursor == CursorType.ResizeDown)
				ctype = NSCursor.ResizeDownCursor;
			else if (cursor == CursorType.ResizeUp)
				ctype = NSCursor.ResizeUpCursor;
			else if (cursor == CursorType.ResizeLeft)
				ctype = NSCursor.ResizeLeftCursor;
			else if (cursor == CursorType.ResizeRight)
				ctype = NSCursor.ResizeRightCursor;
			else if (cursor == CursorType.ResizeLeftRight)
				ctype = NSCursor.ResizeLeftRightCursor;
			else if (cursor == CursorType.ResizeUpDown)
				ctype = NSCursor.ResizeUpDownCursor;
			else
				ctype = NSCursor.ArrowCursor;
			// TODO: assign the cursor
		}
		
		~ViewBackend ()
		{
			Dispose (false);
		}
		
		public void Dispose ()
		{
			GC.SuppressFinalize (this);
			Dispose (true);
		}
		
		protected virtual void Dispose (bool disposing)
		{
		}
		
		public virtual SizeRequestMode SizeRequestMode {
			get { return SizeRequestMode.HeightForWidth; }
		}
		
		Size IWidgetBackend.Size {
			get { return new Size (Widget.WidgetWidth () - Frontend.Margin.HorizontalSpacing, Widget.WidgetHeight () - Frontend.Margin.VerticalSpacing); }
		}
		
		public static NSView GetWidget (IWidgetBackend w)
		{
			return ((ViewBackend)w).Widget;
		}

		public static NSView GetWidget (Widget w)
		{
			return GetWidget ((IWidgetBackend)Toolkit.GetBackend (w));
		}
		
		public virtual object Font {
			get {
				if (Widget is NSControl)
					return ((NSControl)(object)Widget).Font;
				if (Widget is NSText)
					return ((NSText)(object)Widget).Font;
				return NSFont.ControlContentFontOfSize (NSFont.SystemFontSize);
			}
			set {
				if (Widget is NSControl)
					((NSControl)(object)Widget).Font = (NSFont) value;
				if (Widget is NSText)
					((NSText)(object)Widget).Font = (NSFont) value;
				ResetFittingSize ();
			}
		}
		
		public virtual Xwt.Drawing.Color BackgroundColor {
			get;
			set;
		}
		
		#region IWidgetBackend implementation
		
		public Point ConvertToScreenCoordinates (Point widgetCoordinates)
		{
			var lo = Widget.ConvertPointToBase (new PointF ((float)widgetCoordinates.X, (float)widgetCoordinates.Y));
			lo = Widget.Window.ConvertBaseToScreen (lo);
			return MacDesktopBackend.ToDesktopRect (new RectangleF (lo.X, lo.Y, 0, Widget.IsFlipped ? 0 : Widget.Frame.Height)).Location;
		}
		
		protected virtual Size GetNaturalSize ()
		{
//			var s = Widget.FittingSize;
//			return new Size (s.Width, s.Height);
			return lastFittingSize;
		}

		public virtual WidgetSize GetPreferredWidth ()
		{
			var w = GetNaturalSize ().Width;
{'fraction_non_alphanumeric': 0.09260337798485731, 'fraction_numerical': 0.0007765482430596001, 'mean_word_length': 3.25612778848802, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '99091', 'n_tokens_mistral': 5658, 'n_tokens_neox': 4756, 'n_words': 1426}