~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
using System;
using System.IO;
using System.Collections;
using System.Reflection;
using Gtk;

using MonoDevelop.Core;
using MonoDevelop.Core.ProgressMonitoring;

namespace MonoDevelop.Ide.Gui.Dialogs {
	
	public class SplashScreenForm : Window, IProgressMonitor, IDisposable
	{
		ConsoleProgressMonitor monitor = new ConsoleProgressMonitor ();

		const int SplashFontSize = 10;
		const string SplashFontFamily = "sans-serif";

		Gdk.Pixbuf bitmap;
		bool showVersionInfo;

		//this is a popup so it behaves like other splashes on Windows, i.e. doesn't show up as a second window in the taskbar.
		public SplashScreenForm () : base (WindowType.Popup)
		{
			AppPaintable = true;
			this.Decorated = false;
			this.WindowPosition = WindowPosition.Center;
			this.TypeHint = Gdk.WindowTypeHint.Splashscreen;
			this.showVersionInfo = BrandingService.GetBool ("SplashScreen", "ShowVersionInfo") ?? true;
			using (var stream = BrandingService.GetStream ("SplashScreen.png", true))
				bitmap = new Gdk.Pixbuf (stream);
			this.Resize (bitmap.Width, bitmap.Height);
		}
		
		protected override void OnDestroyed ()
		{
			base.OnDestroyed ();
			if (bitmap != null) {
				bitmap.Dispose ();
				bitmap = null;
			}
		}
		
		protected override bool OnExposeEvent (Gdk.EventExpose evt)
		{
			var build = "";
			var version = "v" + BuildVariables.PackageVersionLabel;
			
			var index = version.IndexOf (' ');
			if (index != -1) {
				build = version.Substring (index + 1);
				version = version.Substring (0, index);
			}
			
			if (bitmap != null) {
				using (var context = Gdk.CairoHelper.Create (GdkWindow)) {
					context.Antialias = Cairo.Antialias.Subpixel;
				
					// Render the image first.
					bitmap.RenderToDrawable (GdkWindow, new Gdk.GC (GdkWindow), 0, 0, 0, 0, bitmap.Width, bitmap.Height, Gdk.RgbDither.None, 0, 0);
					
					if (showVersionInfo) {
						var bottomRight = new Cairo.PointD (bitmap.Width - 12, bitmap.Height - 25);
						// Render the alpha/beta text if we're an alpha or beta. If this
						// is rendered, the bottomRight point will be shifted upwards to
						// allow the MonoDevelop version to be rendered above the alpha marker
						if (!string.IsNullOrEmpty (build)) {
							DrawAlphaBetaMarker (context, ref bottomRight, build);
						}
						// Render the MonoDevelop version
						DrawVersionNumber (context, ref bottomRight, version);
					}
				}
			}

			return true;
		}
		
		void DrawVersionNumber (Cairo.Context c, ref Cairo.PointD bottomRight, string text)
		{
			c.SelectFontFace (SplashFontFamily, Cairo.FontSlant.Normal, Cairo.FontWeight.Normal);
			c.SetFontSize (SplashFontSize);
			
			var extents = c.TextExtents (text);
			c.MoveTo (bottomRight.X - extents.Width - 1, bottomRight.Y - extents.Height);
			
			c.Color = new Cairo.Color (1, 1, 1);
			c.ShowText (text);
		}
		
		void DrawAlphaBetaMarker (Cairo.Context c, ref Cairo.PointD bottomRight, string text)
		{
			c.SelectFontFace (SplashFontFamily, Cairo.FontSlant.Normal, Cairo.FontWeight.Bold);
			c.SetFontSize (SplashFontSize);
			
			// Create a rectangle larger than the text so we can have a nice border
			var extents = c.TextExtents (text);
			var x = bottomRight.X - extents.Width * 1.3;
			var y = bottomRight.Y - extents.Height * 1.5;
			var rectangle = new Cairo.Rectangle (x, y, bottomRight.X - x, bottomRight.Y - y);
			
			// Draw the background color the text will be overlaid on
			DrawRoundedRectangle (c, rectangle);
			
			// Calculate the offset the text will need to be at to be centralised
			// in the border
			x = x + extents.XBearing + (rectangle.Width - extents.Width) / 2;
			y = y - extents.YBearing + (rectangle.Height - extents.Height) / 2;
			c.MoveTo (x, y);
			
			// Draw the text
			c.Color = new Cairo.Color (1, 1, 1);
			c.ShowText (text);
			
			bottomRight.Y -= rectangle.Height - 2;
		}
		
		void DrawRoundedRectangle (Cairo.Context c, Cairo.Rectangle rect)
		{
			double x = rect.X;
			double y = rect.Y;
			double width = rect.Width;
			double height = rect.Height;
			double radius = 5;
			
			c.MoveTo (x, y + radius);
			c.Arc (x + radius, y + radius, radius, Math.PI, -Math.PI / 2);
			c.LineTo (x + width - radius, y);
			c.Arc (x + width - radius, y + radius, radius, -Math.PI / 2, 0);
			c.LineTo (x + width, y + height - radius);
			c.Arc (x + width - radius, y + height - radius, radius, 0, Math.PI / 2);
			c.LineTo (x + radius, y + height);
			c.Arc (x + radius, y + height - radius, radius, Math.PI / 2, Math.PI);
			c.ClosePath ();
			
			c.Color = new Cairo.Color (161 / 255.0, 40 / 255.0, 48 / 255.0);
			c.Fill ();
		}
		
		static void RunMainLoop ()
		{
			DispatchService.RunPendingEvents ();
		}
		
		void IProgressMonitor.BeginTask (string name, int totalWork)
		{
			monitor.BeginTask (name, totalWork);
			RunMainLoop ();
		}
		
		void IProgressMonitor.BeginStepTask (string name, int totalWork, int stepSize)
		{
			monitor.BeginStepTask (name, totalWork, stepSize);
			RunMainLoop ();
		}
		
		void IProgressMonitor.EndTask ()
		{
			monitor.EndTask ();
			RunMainLoop ();
		}
		
		void IProgressMonitor.Step (int work)
		{
			monitor.Step (work);
			RunMainLoop ();
		}
		
		TextWriter IProgressMonitor.Log {
			get { return monitor.Log; }
		}
		
		void IProgressMonitor.ReportWarning (string message)
		{
			monitor.ReportWarning (message);
		}
		
		void IProgressMonitor.ReportSuccess (string message)
		{
			monitor.ReportSuccess (message);
		}
		
		void IProgressMonitor.ReportError (string message, Exception exception)
		{
			monitor.ReportError (message, exception);
		}
		
		bool IProgressMonitor.IsCancelRequested {
			get { return false; }
		}
		
		public event MonitorHandler CancelRequested {
			add { }
			remove { }
		}
		
		// The returned IAsyncOperation object must be thread safe
		IAsyncOperation IProgressMonitor.AsyncOperation {
			get { return monitor.AsyncOperation; }
		}
		
		object IProgressMonitor.SyncRoot {
			get { return monitor.SyncRoot; }
		}
		
		void IDisposable.Dispose ()
		{
			Destroy ();
		}
	}
}