summaryrefslogtreecommitdiff
path: root/platform/windows/gsview/gsprintbg.cs
blob: 199258e32b2ab20e683dcb4a653fc72e03179f07 (plain)
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.IO;
using System.IO.Packaging;
using System.Printing;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Documents.Serialization;
using System.Windows.Media;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using System.Windows.Xps.Serialization;
using System.Threading;

namespace gsview
{
	public enum PrintStatus_t
	{
		PRINT_READY,
		PRINT_BUSY,
		PRINT_ERROR
	};

	public enum PrintResult_t
	{
		PrintOK,
		PrintFAILED,
		PrintCANCELLED,
		PrintCOMPLETED
	}

	public struct PrintParams_t
	{
		public int num_pages;
		public int start_page;
		public int end_page;
		public PrintQueue queu;
		public FixedDocumentSequence fixdoc;
		public PrintResult_t result;
		public PrintStatus_t status;

	};

	public class PrintEventArgs : EventArgs
	{
		private PrintStatus_t m_status;
		private PrintResult_t m_result;
		private int m_percentdone;

		public PrintStatus_t Status
		{
			get { return m_status; }
		}

		public PrintResult_t Result
		{
			get { return m_result; }
		}

		public int Percent
		{
			get { return m_percentdone; }
		}

		public PrintEventArgs(PrintStatus_t status, PrintResult_t completed, int percent)
		{
			m_status = status;
			m_result = completed;
			m_percentdone = percent;
		}
	}

	public class gsprintbg
	{
		BackgroundWorker m_worker;
		private XpsDocumentWriter m_docWriter = null;
		PrintParams_t m_pparams;

		internal delegate void PrintCallBackMain(object gsObject, PrintEventArgs info);
		internal event PrintCallBackMain PrintUpdateMain;

		private void PrintProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			/* Callback with progress */
			PrintEventArgs info = new PrintEventArgs(m_pparams.status, m_pparams.result, e.ProgressPercentage);
			if (PrintUpdateMain != null)
				PrintUpdateMain(this, info);
		}

		/* Callback */
		private void PrintCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			PrintParams_t Value;
			PrintEventArgs info;
			PrintParams_t Params = (PrintParams_t)e.Result;

			if (e.Cancelled)
			{
				info = new PrintEventArgs(PrintStatus_t.PRINT_READY, PrintResult_t.PrintCANCELLED, 100);
			}
			else
			{
				Value = (PrintParams_t)e.Result;
				info = new PrintEventArgs(PrintStatus_t.PRINT_READY, PrintResult_t.PrintCOMPLETED, 100);
			}
			PrintUpdateMain(this, info);
		}


		/* Show std. print dialog */
		public PrintDialog GetPrintDialog()
		{
			PrintDialog dlg = new PrintDialog();
			/* Current page and page ranges is going to require a little work */
			dlg.PageRangeSelection = PageRangeSelection.AllPages;
			//dlg.UserPageRangeEnabled = true;
			//dlg.CurrentPageEnabled = true;
			dlg.SelectedPagesEnabled = false;
			if (dlg.ShowDialog() == true)
				return dlg;
			return null;
		}

		/* Main print entry point */
		private void Print(PrintParams_t pparams)
		{
			XpsDocumentWriter docwrite = GetDocWriter(pparams.queu);
			docwrite.WritingPrintTicketRequired +=
				new WritingPrintTicketRequiredEventHandler(PrintTicket);
			PrintPages(docwrite, pparams.fixdoc);
		}

		/* Send it */
		private void PrintPages(XpsDocumentWriter xpsdw, FixedDocumentSequence fixdoc)
		{
			m_docWriter = xpsdw;
			xpsdw.WritingCompleted +=
				new WritingCompletedEventHandler(AsyncCompleted);
			xpsdw.WritingProgressChanged +=
				new WritingProgressChangedEventHandler(AsyncProgress);
			xpsdw.WriteAsync(fixdoc);
		}

		private void CancelAsync()
		{
			/* ick.  This does not work in windows 8. causes crash */
			/* https://connect.microsoft.com/VisualStudio/feedback/details/778145/xpsdocumentwriter-cancelasync-cause-crash-in-win8 */
			m_docWriter.CancelAsync();
		}

		/* Done */
		private void AsyncCompleted(object sender, WritingCompletedEventArgs e)
		{
			if (e.Cancelled)
				m_pparams.result = PrintResult_t.PrintCANCELLED;
			else if (e.Error != null)
				m_pparams.result = PrintResult_t.PrintFAILED;
			else
				m_pparams.result = PrintResult_t.PrintCOMPLETED;
			m_worker.ReportProgress(100);
		}

		/* Do this update with each fixed document (page) that is handled */
		private void AsyncProgress(object sender, WritingProgressChangedEventArgs e)
		{
			double perc = 100.0 * (double) e.Number / (double) m_pparams.num_pages;
			m_worker.ReportProgress((int) perc);
		}

		/* Print ticket handling. You can customize for PrintTicketLevel at
		  FixedDocumentSequencePrintTicket, FixedDocumentPrintTicket,
		 or FixedPagePrintTicket.  We may want to play around with this some */
		private void PrintTicket(Object sender, WritingPrintTicketRequiredEventArgs e)
		{
			if (e.CurrentPrintTicketLevel ==
					PrintTicketLevel.FixedDocumentSequencePrintTicket)
			{
				PrintTicket pts = new PrintTicket();
				pts.PageOrientation = PageOrientation.Portrait;
				e.CurrentPrintTicket = pts;
			}
		}

		/* Create the document write */
		private XpsDocumentWriter GetDocWriter(PrintQueue pq)
		{
			XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(pq);
			return xpsdw;
		}


		private void PrintWork(object sender, DoWorkEventArgs e)
		{
			PrintParams_t PParams = (PrintParams_t)e.Argument;
			BackgroundWorker worker = sender as BackgroundWorker;

			Print(PParams);
		}

		public bool IsBusy()
		{
			if (m_worker != null)
				return m_worker.IsBusy;
			else
				return false;
		}

		public void PrintWorkThread(object data)
		{
			PrintParams_t PParams = (PrintParams_t) data;
			Print(PParams);
		}
		
		public PrintStatus_t StartPrint(PrintParams_t pparams)
		{
			try
			{
				if (m_worker != null && m_worker.IsBusy)
				{
					m_worker.CancelAsync();
					return PrintStatus_t.PRINT_BUSY;
				}

				if (m_worker == null)
				{

					Thread asyncThread = new Thread(PrintWorkThread);
					asyncThread.SetApartmentState(ApartmentState.STA);
					asyncThread.Start(pparams);

				/*	m_worker = new BackgroundWorker();
					m_worker.WorkerReportsProgress = true;
					m_worker.WorkerSupportsCancellation = true;
					m_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(PrintCompleted);
					m_worker.ProgressChanged += new ProgressChangedEventHandler(PrintProgressChanged);
					m_worker.DoWork += new DoWorkEventHandler(PrintWork);*/
				}

				////m_pparams = pparams;
				//m_worker.RunWorkerAsync(pparams);
				pparams.status = PrintStatus_t.PRINT_BUSY;
				return PrintStatus_t.PRINT_READY;
			}
			catch (OutOfMemoryException e)
			{
				Console.WriteLine("Memory allocation failed during printing\n");
				return PrintStatus_t.PRINT_ERROR;
			}
		}


		public void Cancel()
		{
			m_worker.CancelAsync();
		}
	}
}