Implement the drawing of mixed-mode check boxes
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / PrintPreviewControl.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2006 Novell, Inc.
21 //
22 // Authors:
23 //      Jonathan Chambers (jonathan.chambers@ansys.com)
24 //
25
26 using System;
27 using System.ComponentModel;
28 using System.ComponentModel.Design;
29 using System.ComponentModel.Design.Serialization;
30 using System.Collections;
31 using System.Diagnostics;
32 using System.Drawing;
33 using System.Drawing.Printing;
34 using System.Reflection;
35 using System.Runtime.InteropServices;
36
37 namespace System.Windows.Forms {
38         [DefaultPropertyAttribute("Document")]
39         [ClassInterface (ClassInterfaceType.AutoDispatch)]
40         [ComVisible (true)]
41         public class PrintPreviewControl : Control {
42                 #region Local variables
43                 bool autozoom;
44                 int columns;
45                 int rows;
46                 int startPage;
47                 double zoom;
48                 int padding = ThemeEngine.Current.PrintPreviewControlPadding;
49                 PrintDocument document;
50                 internal PreviewPrintController controller;
51                 internal PreviewPageInfo[] page_infos;
52                 private VScrollBar vbar;
53                 private HScrollBar hbar;
54
55                 internal Rectangle ViewPort;
56                 internal Image[] image_cache;
57                 Size image_size;
58
59                 #endregion // Local variables
60
61                 #region Public Constructors
62                 public PrintPreviewControl() {
63                         autozoom = true;
64                         columns = 1;
65                         rows = 0;
66                         startPage = 1;
67
68                         this.BackColor = SystemColors.AppWorkspace;
69
70                         controller = new PreviewPrintController ();
71
72                         vbar = new ImplicitVScrollBar ();
73                         hbar = new ImplicitHScrollBar ();
74
75                         vbar.Visible = false;
76                         hbar.Visible = false;
77                         vbar.ValueChanged += new EventHandler (VScrollBarValueChanged);
78                         hbar.ValueChanged += new EventHandler (HScrollBarValueChanged);
79
80                         SuspendLayout ();
81                         Controls.AddImplicit (vbar);
82                         Controls.AddImplicit (hbar);
83                         ResumeLayout ();
84                 }
85                 #endregion // Public Constructors
86
87                 
88                 #region Public Instance Properties
89                 [DefaultValue(true)]
90                 public bool AutoZoom {
91                         get { return autozoom; }
92                         set {
93                                 autozoom = value;
94                                 InvalidateLayout ();
95                         }
96                 }
97                 [DefaultValue(1)]
98                 public int Columns {
99                         get { return columns; }
100                         set {
101                                 columns = value;
102                                 InvalidateLayout ();
103                         }
104                 }
105                 [DefaultValue(null)]
106                 public PrintDocument Document {
107                         get { return document; }
108                         set {
109                                 document = value;
110                         }
111                 }
112
113                 [Localizable (true)]
114                 [AmbientValue (RightToLeft.Inherit)]
115                 public override RightToLeft RightToLeft {
116                         get { return base.RightToLeft; }
117                         set { base.RightToLeft = value; }
118                 }
119
120                 [DefaultValue(1)]
121                 public int Rows {
122                         get { return rows; }
123                         set {
124                                 rows = value;
125                                 InvalidateLayout ();
126                         }
127                 }
128                 [DefaultValue(0)]
129                 public int StartPage {
130                         get { return startPage; }
131                         set {
132                                 if (value < 1)
133                                         return;
134                                 if (document != null && value + (Rows + 1) * Columns > page_infos.Length + 1) {
135                                         value = page_infos.Length + 1 - (Rows + 1) * Columns;
136                                         if (value < 1)
137                                                 value = 1;
138                                 }
139
140                                 int start = StartPage;
141                                 startPage = value;
142                                 if (start != startPage) {
143                                         InvalidateLayout ();
144                                         OnStartPageChanged (EventArgs.Empty);
145                                 }
146                         }
147                 }
148
149                 [Bindable(false)]
150                 [Browsable(false)]
151                 [EditorBrowsable(EditorBrowsableState.Never)]
152                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
153                 public override string Text {
154                         get { return base.Text; }
155                         set { base.Text = value; }
156                 }
157
158                 [DefaultValue(false)]
159                 public bool UseAntiAlias {
160                         get { return controller.UseAntiAlias; }
161                         set { controller.UseAntiAlias = value; }
162                 }
163
164                 [DefaultValue (0.3)]
165                 public double Zoom {
166                         get { return zoom; }
167                         set {
168                                 if (value <= 0)
169                                         throw new ArgumentException ("zoom");
170                                 autozoom = false;
171                                 zoom = value;
172                                 InvalidateLayout ();                            
173                         }
174                 }
175                 #endregion // Public Instance Properties
176
177                 
178                 #region Public Instance Methods
179                 internal void GeneratePreview ()
180                 {
181                         if (document == null)
182                                 return;
183
184                         try {
185                                 if (page_infos == null) {
186                                         if (document.PrintController == null || !(document.PrintController is PrintControllerWithStatusDialog)) {
187                                                 document.PrintController = new PrintControllerWithStatusDialog (controller);
188                                         }
189                                         document.Print ();
190                                         page_infos = controller.GetPreviewPageInfo ();
191                                 }
192                                 
193                                 if (image_cache == null) {
194                                         image_cache = new Image[page_infos.Length];
195
196                                         if (page_infos.Length > 0) {
197                                                 image_size = ThemeEngine.Current.PrintPreviewControlGetPageSize (this);
198                                                 if (image_size.Width >= 0 && image_size.Width < page_infos[0].Image.Width
199                                                     && image_size.Height >= 0 && image_size.Height < page_infos[0].Image.Height) {
200
201                                                         for (int i = 0; i < page_infos.Length; i ++) {
202                                                                 image_cache[i] = new Bitmap (image_size.Width, image_size.Height);
203                                                                 Graphics g = Graphics.FromImage (image_cache[i]);
204                                                                 g.DrawImage (page_infos[i].Image, new Rectangle (new Point (0, 0), image_size), 0, 0, page_infos[i].Image.Width, page_infos[i].Image.Height, GraphicsUnit.Pixel);
205                                                                 g.Dispose ();
206                                                         }
207                                                 }
208                                         }
209                                 }
210                                 UpdateScrollBars();
211                         }
212                         catch (Exception e) {
213                                 page_infos = new PreviewPageInfo[0];
214                                 image_cache = new Image[0];
215                                 MessageBox.Show (e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
216                         }
217                 }
218
219                 public void InvalidatePreview()
220                 {
221                         if (page_infos != null) {
222                                 for (int i = 0; i < page_infos.Length; i++) {
223                                         if (page_infos[i].Image != null) {
224                                                 page_infos[i].Image.Dispose();
225                                         }
226                                 }
227                                 page_infos = null;
228                         }
229                         InvalidateLayout();
230                 }
231
232                 [EditorBrowsable(EditorBrowsableState.Never)]
233                 public override void ResetBackColor()
234                 {
235                         base.ResetBackColor();
236                 }
237
238                 [EditorBrowsable(EditorBrowsableState.Never)]
239                 public override void ResetForeColor()
240                 {
241                         base.ResetForeColor ();
242                 }
243                 #endregion // Public Instance Methods
244
245                 #region Protected Instance Properties
246                 protected override CreateParams CreateParams {
247                         get {
248                                 return base.CreateParams;
249                         }
250                 }
251
252                 #endregion // Protected Instance Methods
253
254                 #region Protected Instance Properties
255
256                 protected override void OnPaint(PaintEventArgs pevent)
257                 {
258                         if (page_infos == null || image_cache == null)
259                                 GeneratePreview ();
260                         ThemeEngine.Current.PrintPreviewControlPaint (pevent, this, image_size);
261                 }
262
263                 protected override void OnResize(EventArgs eventargs)
264                 {
265                         InvalidateLayout ();
266                         base.OnResize (eventargs);
267                 }
268
269                 protected virtual void OnStartPageChanged(EventArgs e)
270                 {
271                         EventHandler eh = (EventHandler)(Events [StartPageChangedEvent]);
272                         if (eh != null)
273                                 eh (this, e);
274                 }
275
276                 protected override void WndProc(ref Message m)
277                 {
278                         base.WndProc (ref m);
279                 }
280
281                 #endregion // Protected Instance Methods
282
283                 static object StartPageChangedEvent = new object ();
284
285                 public event EventHandler StartPageChanged {
286                         add { Events.AddHandler (StartPageChangedEvent, value); }
287                         remove { Events.RemoveHandler (StartPageChangedEvent, value); }
288                 }
289
290                 [Browsable(false)]
291                 [EditorBrowsable(EditorBrowsableState.Never)]
292                 public new event EventHandler TextChanged {
293                         add { base.TextChanged += value; }
294                         remove { base.TextChanged -= value; }
295                 }
296
297                 internal int vbar_value;
298                 internal int hbar_value;
299
300                 #region UIA Framework Property
301                 internal ScrollBar UIAVScrollBar {
302                         get { return vbar; }
303                 }
304
305                 internal ScrollBar UIAHScrollBar {
306                         get { return hbar; }
307                 }
308                 #endregion
309
310                 private void VScrollBarValueChanged (object sender, EventArgs e)
311                 {
312                         int pixels;
313
314                         if (vbar.Value > vbar_value)
315                                 pixels = -1 * (vbar.Value - vbar_value);
316                         else
317                                 pixels = vbar_value - vbar.Value;
318
319                         vbar_value = vbar.Value;
320                         XplatUI.ScrollWindow (Handle, ViewPort, 0, pixels, false);
321                 }
322
323
324                 private void HScrollBarValueChanged (object sender, EventArgs e)
325                 {
326                         int pixels;
327
328                         if (hbar.Value > hbar_value)
329                                 pixels = -1 * (hbar.Value - hbar_value);
330                         else
331                                 pixels = hbar_value - hbar.Value;
332
333                         hbar_value = hbar.Value;
334                         XplatUI.ScrollWindow (Handle, ViewPort, pixels, 0, false);
335                 }
336
337                 private void UpdateScrollBars ()
338                 {
339                         ViewPort = ClientRectangle;
340                         if (AutoZoom)
341                                 return;
342
343                         int total_width, total_height;
344
345                         total_width = image_size.Width * Columns + (Columns + 1) * padding;
346                         total_height = image_size.Height * (Rows + 1) + (Rows + 2) * padding;
347
348                         bool vert = false;
349                         bool horz = false;
350
351                         if (total_width > ClientRectangle.Width) {
352                                 /* we need the hbar */
353                                 horz = true;
354                                 ViewPort.Height -= hbar.Height;
355                         }
356                         if (total_height > ViewPort.Height) {
357                                 /* we need the vbar */
358                                 vert = true;
359                                 ViewPort.Width -= vbar.Width;
360                         }
361                         if (!horz && total_width > ViewPort.Width) {
362                                 horz = true;
363                                 ViewPort.Height -= hbar.Height;
364                         }
365
366                         SuspendLayout ();
367
368                         if (vert) {
369                                 vbar.SetValues (total_height, ViewPort.Height);
370
371                                 vbar.Bounds = new Rectangle (ClientRectangle.Width - vbar.Width, 0, vbar.Width,
372                                                              ClientRectangle.Height -
373                                                              (horz ? SystemInformation.VerticalScrollBarWidth : 0));
374                                 vbar.Visible = true;
375                                 vbar_value = vbar.Value;
376                         }
377                         else {
378                                 vbar.Visible = false;
379                         }
380
381                         if (horz) {
382                                 hbar.SetValues (total_width, ViewPort.Width);
383
384                                 hbar.Bounds = new Rectangle (0, ClientRectangle.Height - hbar.Height,
385                                                              ClientRectangle.Width - (vert ?
386                                                                                       SystemInformation.HorizontalScrollBarHeight : 0),
387                                                              hbar.Height);
388                                 hbar.Visible = true;
389                                 hbar_value = hbar.Value;
390                         }
391                         else {
392                                 hbar.Visible = false;
393                         }
394
395                         ResumeLayout (false);
396                 }
397
398                 private void InvalidateLayout() {
399                         if (image_cache != null) {
400                                 for (int i = 0; i < image_cache.Length; i++) {
401                                         if (image_cache[i] !=null)
402                                                 image_cache[i].Dispose();
403                                 }
404                                 image_cache = null;
405                         }
406                         Invalidate ();
407                 }
408         }
409 }