Deprecate wxDC::{Begin,End}Drawing()
[wxWidgets.git] / src / generic / colrdlgg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/colrdlgg.cpp
3 // Purpose: Choice dialogs
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_COLOURDLG && (!defined(__WXGTK20__) || defined(__WXUNIVERSAL__))
20
21 #ifndef WX_PRECOMP
22 #include "wx/utils.h"
23 #include "wx/intl.h"
24 #include "wx/dialog.h"
25 #include "wx/listbox.h"
26 #include "wx/button.h"
27 #include "wx/stattext.h"
28 #include "wx/layout.h"
29 #include "wx/dcclient.h"
30 #include "wx/sizer.h"
31 #endif
32
33 #if wxUSE_STATLINE
34 #include "wx/statline.h"
35 #endif
36
37 #if wxUSE_SLIDER
38 #include "wx/slider.h"
39 #endif
40
41 #include "wx/generic/colrdlgg.h"
42
43 IMPLEMENT_DYNAMIC_CLASS(wxGenericColourDialog, wxDialog)
44
45 BEGIN_EVENT_TABLE(wxGenericColourDialog, wxDialog)
46 EVT_BUTTON(wxID_ADD_CUSTOM, wxGenericColourDialog::OnAddCustom)
47 #if wxUSE_SLIDER
48 EVT_SLIDER(wxID_RED_SLIDER, wxGenericColourDialog::OnRedSlider)
49 EVT_SLIDER(wxID_GREEN_SLIDER, wxGenericColourDialog::OnGreenSlider)
50 EVT_SLIDER(wxID_BLUE_SLIDER, wxGenericColourDialog::OnBlueSlider)
51 #endif
52 EVT_PAINT(wxGenericColourDialog::OnPaint)
53 EVT_MOUSE_EVENTS(wxGenericColourDialog::OnMouseEvent)
54 EVT_CLOSE(wxGenericColourDialog::OnCloseWindow)
55 END_EVENT_TABLE()
56
57
58 /*
59 * Generic wxColourDialog
60 */
61
62 // don't change the number of elements (48) in this array, the code below is
63 // hardcoded to use it
64 static const wxChar *wxColourDialogNames[] =
65 {
66 wxT("ORANGE"),
67 wxT("GOLDENROD"),
68 wxT("WHEAT"),
69 wxT("SPRING GREEN"),
70 wxT("SKY BLUE"),
71 wxT("SLATE BLUE"),
72 wxT("MEDIUM VIOLET RED"),
73 wxT("PURPLE"),
74
75 wxT("RED"),
76 wxT("YELLOW"),
77 wxT("MEDIUM SPRING GREEN"),
78 wxT("PALE GREEN"),
79 wxT("CYAN"),
80 wxT("LIGHT STEEL BLUE"),
81 wxT("ORCHID"),
82 wxT("LIGHT MAGENTA"),
83
84 wxT("BROWN"),
85 wxT("YELLOW"),
86 wxT("GREEN"),
87 wxT("CADET BLUE"),
88 wxT("MEDIUM BLUE"),
89 wxT("MAGENTA"),
90 wxT("MAROON"),
91 wxT("ORANGE RED"),
92
93 wxT("FIREBRICK"),
94 wxT("CORAL"),
95 wxT("FOREST GREEN"),
96 wxT("AQUAMARINE"),
97 wxT("BLUE"),
98 wxT("NAVY"),
99 wxT("THISTLE"),
100 wxT("MEDIUM VIOLET RED"),
101
102 wxT("INDIAN RED"),
103 wxT("GOLD"),
104 wxT("MEDIUM SEA GREEN"),
105 wxT("MEDIUM BLUE"),
106 wxT("MIDNIGHT BLUE"),
107 wxT("GREY"),
108 wxT("PURPLE"),
109 wxT("KHAKI"),
110
111 wxT("BLACK"),
112 wxT("MEDIUM FOREST GREEN"),
113 wxT("KHAKI"),
114 wxT("DARK GREY"),
115 wxT("SEA GREEN"),
116 wxT("LIGHT GREY"),
117 wxT("MEDIUM SLATE BLUE"),
118 wxT("WHITE")
119 };
120
121 wxGenericColourDialog::wxGenericColourDialog()
122 {
123 dialogParent = NULL;
124 whichKind = 1;
125 colourSelection = -1;
126 }
127
128 wxGenericColourDialog::wxGenericColourDialog(wxWindow *parent,
129 wxColourData *data)
130 {
131 whichKind = 1;
132 colourSelection = -1;
133 Create(parent, data);
134 }
135
136 wxGenericColourDialog::~wxGenericColourDialog()
137 {
138 }
139
140 void wxGenericColourDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
141 {
142 EndModal(wxID_CANCEL);
143 }
144
145 bool wxGenericColourDialog::Create(wxWindow *parent, wxColourData *data)
146 {
147 if ( !wxDialog::Create(parent, wxID_ANY, _("Choose colour"),
148 wxPoint(0,0), wxSize(900, 900)) )
149 return false;
150
151 dialogParent = parent;
152
153 if (data)
154 colourData = *data;
155
156 InitializeColours();
157 CalculateMeasurements();
158 CreateWidgets();
159
160 return true;
161 }
162
163 int wxGenericColourDialog::ShowModal()
164 {
165 return wxDialog::ShowModal();
166 }
167
168
169 // Internal functions
170 void wxGenericColourDialog::OnMouseEvent(wxMouseEvent& event)
171 {
172 if (event.ButtonDown(1))
173 {
174 int x = (int)event.GetX();
175 int y = (int)event.GetY();
176
177 #ifdef __WXPM__
178 // Handle OS/2's reverse coordinate system and account for the dialog title
179 int nClientHeight;
180
181 GetClientSize(NULL, &nClientHeight);
182 y = (nClientHeight - y) + 20;
183 #endif
184 if ((x >= standardColoursRect.x && x <= (standardColoursRect.x + standardColoursRect.width)) &&
185 (y >= standardColoursRect.y && y <= (standardColoursRect.y + standardColoursRect.height)))
186 {
187 int selX = (int)(x - standardColoursRect.x)/(smallRectangleSize.x + gridSpacing);
188 int selY = (int)(y - standardColoursRect.y)/(smallRectangleSize.y + gridSpacing);
189 int ptr = (int)(selX + selY*8);
190 OnBasicColourClick(ptr);
191 }
192 else if ((x >= customColoursRect.x && x <= (customColoursRect.x + customColoursRect.width)) &&
193 (y >= customColoursRect.y && y <= (customColoursRect.y + customColoursRect.height)))
194 {
195 int selX = (int)(x - customColoursRect.x)/(smallRectangleSize.x + gridSpacing);
196 int selY = (int)(y - customColoursRect.y)/(smallRectangleSize.y + gridSpacing);
197 int ptr = (int)(selX + selY*8);
198 OnCustomColourClick(ptr);
199 }
200 else
201 event.Skip();
202 }
203 else
204 event.Skip();
205 }
206
207 void wxGenericColourDialog::OnPaint(wxPaintEvent& event)
208 {
209 #if !defined(__WXMOTIF__) && !defined(__WXPM__) && !defined(__WXCOCOA__)
210 wxDialog::OnPaint(event);
211 #else
212 wxUnusedVar(event);
213 #endif
214
215 wxPaintDC dc(this);
216
217 PaintBasicColours(dc);
218 PaintCustomColours(dc);
219 PaintCustomColour(dc);
220 PaintHighlight(dc, true);
221 }
222
223 void wxGenericColourDialog::CalculateMeasurements()
224 {
225 smallRectangleSize.x = 18;
226 smallRectangleSize.y = 14;
227 customRectangleSize.x = 40;
228 customRectangleSize.y = 40;
229
230 gridSpacing = 6;
231 sectionSpacing = 15;
232
233 standardColoursRect.x = 10;
234 #ifdef __WXPM__
235 standardColoursRect.y = 15 + 20; /* OS/2 needs to account for dialog titlebar */
236 #else
237 standardColoursRect.y = 15;
238 #endif
239 standardColoursRect.width = (8*smallRectangleSize.x) + (7*gridSpacing);
240 standardColoursRect.height = (6*smallRectangleSize.y) + (5*gridSpacing);
241
242 customColoursRect.x = standardColoursRect.x;
243 customColoursRect.y = standardColoursRect.y + standardColoursRect.height + 20;
244 customColoursRect.width = (8*smallRectangleSize.x) + (7*gridSpacing);
245 customColoursRect.height = (2*smallRectangleSize.y) + (1*gridSpacing);
246
247 singleCustomColourRect.x = customColoursRect.width + customColoursRect.x + sectionSpacing;
248 singleCustomColourRect.y = 80;
249 singleCustomColourRect.width = customRectangleSize.x;
250 singleCustomColourRect.height = customRectangleSize.y;
251
252 okButtonX = 10;
253 customButtonX = singleCustomColourRect.x ;
254 buttonY = customColoursRect.y + customColoursRect.height + 10;
255 }
256
257 void wxGenericColourDialog::CreateWidgets()
258 {
259 wxBeginBusyCursor();
260
261 wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
262
263 const int sliderHeight = 160;
264
265 #if wxUSE_SLIDER
266 const int sliderX = singleCustomColourRect.x + singleCustomColourRect.width + sectionSpacing;
267
268 redSlider = new wxSlider(this, wxID_RED_SLIDER, colourData.m_dataColour.Red(), 0, 255,
269 wxDefaultPosition, wxSize(wxDefaultCoord, sliderHeight), wxSL_VERTICAL|wxSL_LABELS|wxSL_INVERSE);
270 greenSlider = new wxSlider(this, wxID_GREEN_SLIDER, colourData.m_dataColour.Green(), 0, 255,
271 wxDefaultPosition, wxSize(wxDefaultCoord, sliderHeight), wxSL_VERTICAL|wxSL_LABELS|wxSL_INVERSE);
272 blueSlider = new wxSlider(this, wxID_BLUE_SLIDER, colourData.m_dataColour.Blue(), 0, 255,
273 wxDefaultPosition, wxSize(wxDefaultCoord, sliderHeight), wxSL_VERTICAL|wxSL_LABELS|wxSL_INVERSE);
274
275 wxBoxSizer *sliderSizer = new wxBoxSizer( wxHORIZONTAL );
276
277 // 1) space for sliders
278 sliderSizer->Add( sliderX, sliderHeight );
279 sliderSizer->Add( redSlider, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 10 );
280 sliderSizer->Add( greenSlider, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 10 );
281 sliderSizer->Add( blueSlider, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 10 );
282
283 topSizer->Add( sliderSizer, 0, wxCENTRE | wxALL, 10 );
284 #else
285 topSizer->Add( 1, sliderHeight, 0, wxCENTRE | wxALL, 15 );
286 #endif // wxUSE_SLIDER
287
288 #if wxUSE_STATLINE
289 // 2) static line
290 topSizer->Add( new wxStaticLine( this, wxID_ANY ), 0, wxEXPAND | wxLEFT|wxRIGHT|wxTOP, 10 );
291 #endif
292
293 // 3) buttons
294 wxSizer *buttonsizer = CreateButtonSizer( wxOK|wxCANCEL );
295 buttonsizer->Add( new wxButton(this, wxID_ADD_CUSTOM, _("Add to custom colours") ), 0, wxLEFT|wxRIGHT, 10 );
296 topSizer->Add( buttonsizer, 0, wxEXPAND | wxALL, 10 );
297
298 SetAutoLayout( true );
299 SetSizer( topSizer );
300
301 topSizer->SetSizeHints( this );
302 topSizer->Fit( this );
303
304 Centre( wxBOTH );
305
306 wxEndBusyCursor();
307 }
308
309 void wxGenericColourDialog::InitializeColours(void)
310 {
311 size_t i;
312
313 for (i = 0; i < WXSIZEOF(wxColourDialogNames); i++)
314 {
315 wxColour col = wxTheColourDatabase->Find(wxColourDialogNames[i]);
316 if (col.Ok())
317 standardColours[i].Set(col.Red(), col.Green(), col.Blue());
318 else
319 standardColours[i].Set(0, 0, 0);
320 }
321
322 for (i = 0; i < WXSIZEOF(customColours); i++)
323 {
324 wxColour c = colourData.GetCustomColour(i);
325 if (c.Ok())
326 customColours[i] = colourData.GetCustomColour(i);
327 else
328 customColours[i] = wxColour(255, 255, 255);
329 }
330
331 wxColour curr = colourData.GetColour();
332 if ( curr.Ok() )
333 {
334 bool initColourFound = false;
335
336 for (i = 0; i < WXSIZEOF(wxColourDialogNames); i++)
337 {
338 if ( standardColours[i] == curr && !initColourFound )
339 {
340 whichKind = 1;
341 colourSelection = i;
342 initColourFound = true;
343 break;
344 }
345 }
346 if ( !initColourFound )
347 {
348 for ( i = 0; i < WXSIZEOF(customColours); i++ )
349 {
350 if ( customColours[i] == curr )
351 {
352 whichKind = 2;
353 colourSelection = i;
354 break;
355 }
356 }
357 }
358 colourData.m_dataColour.Set( curr.Red(), curr.Green(), curr.Blue() );
359 }
360 else
361 {
362 whichKind = 1;
363 colourSelection = 0;
364 colourData.m_dataColour.Set( 0, 0, 0 );
365 }
366 }
367
368 void wxGenericColourDialog::PaintBasicColours(wxDC& dc)
369 {
370 int i;
371 for (i = 0; i < 6; i++)
372 {
373 int j;
374 for (j = 0; j < 8; j++)
375 {
376 int ptr = i*8 + j;
377
378 int x = (j*(smallRectangleSize.x+gridSpacing) + standardColoursRect.x);
379 int y = (i*(smallRectangleSize.y+gridSpacing) + standardColoursRect.y);
380
381 dc.SetPen(*wxBLACK_PEN);
382 wxBrush brush(standardColours[ptr], wxSOLID);
383 dc.SetBrush(brush);
384
385 dc.DrawRectangle( x, y, smallRectangleSize.x, smallRectangleSize.y);
386 }
387 }
388 }
389
390 void wxGenericColourDialog::PaintCustomColours(wxDC& dc)
391 {
392 int i;
393 for (i = 0; i < 2; i++)
394 {
395 int j;
396 for (j = 0; j < 8; j++)
397 {
398 int ptr = i*8 + j;
399
400 int x = (j*(smallRectangleSize.x+gridSpacing)) + customColoursRect.x;
401 int y = (i*(smallRectangleSize.y+gridSpacing)) + customColoursRect.y;
402
403 dc.SetPen(*wxBLACK_PEN);
404
405 wxBrush brush(customColours[ptr], wxSOLID);
406 dc.SetBrush(brush);
407
408 dc.DrawRectangle( x, y, smallRectangleSize.x, smallRectangleSize.y);
409 }
410 }
411 }
412
413 void wxGenericColourDialog::PaintHighlight(wxDC& dc, bool draw)
414 {
415 if ( colourSelection < 0 )
416 return;
417
418 // Number of pixels bigger than the standard rectangle size
419 // for drawing a highlight
420 int deltaX = 2;
421 int deltaY = 2;
422
423 if (whichKind == 1)
424 {
425 // Standard colours
426 int y = (int)(colourSelection / 8);
427 int x = (int)(colourSelection - (y*8));
428
429 x = (x*(smallRectangleSize.x + gridSpacing) + standardColoursRect.x) - deltaX;
430 y = (y*(smallRectangleSize.y + gridSpacing) + standardColoursRect.y) - deltaY;
431
432 if (draw)
433 dc.SetPen(*wxBLACK_PEN);
434 else
435 dc.SetPen(*wxLIGHT_GREY_PEN);
436
437 dc.SetBrush(*wxTRANSPARENT_BRUSH);
438 dc.DrawRectangle( x, y, (smallRectangleSize.x + (2*deltaX)), (smallRectangleSize.y + (2*deltaY)));
439 }
440 else
441 {
442 // User-defined colours
443 int y = (int)(colourSelection / 8);
444 int x = (int)(colourSelection - (y*8));
445
446 x = (x*(smallRectangleSize.x + gridSpacing) + customColoursRect.x) - deltaX;
447 y = (y*(smallRectangleSize.y + gridSpacing) + customColoursRect.y) - deltaY;
448
449 if (draw)
450 dc.SetPen(*wxBLACK_PEN);
451 else
452 dc.SetPen(*wxLIGHT_GREY_PEN);
453
454 dc.SetBrush(*wxTRANSPARENT_BRUSH);
455 dc.DrawRectangle( x, y, (smallRectangleSize.x + (2*deltaX)), (smallRectangleSize.y + (2*deltaY)));
456 }
457 }
458
459 void wxGenericColourDialog::PaintCustomColour(wxDC& dc)
460 {
461 dc.SetPen(*wxBLACK_PEN);
462
463 wxBrush *brush = new wxBrush(colourData.m_dataColour, wxSOLID);
464 dc.SetBrush(*brush);
465
466 dc.DrawRectangle( singleCustomColourRect.x, singleCustomColourRect.y,
467 customRectangleSize.x, customRectangleSize.y);
468
469 dc.SetBrush(wxNullBrush);
470 delete brush;
471 }
472
473 void wxGenericColourDialog::OnBasicColourClick(int which)
474 {
475 wxClientDC dc(this);
476
477 PaintHighlight(dc, false);
478 whichKind = 1;
479 colourSelection = which;
480
481 #if wxUSE_SLIDER
482 redSlider->SetValue( standardColours[colourSelection].Red() );
483 greenSlider->SetValue( standardColours[colourSelection].Green() );
484 blueSlider->SetValue( standardColours[colourSelection].Blue() );
485 #endif // wxUSE_SLIDER
486
487 colourData.m_dataColour.Set(standardColours[colourSelection].Red(),
488 standardColours[colourSelection].Green(),
489 standardColours[colourSelection].Blue());
490
491 PaintCustomColour(dc);
492 PaintHighlight(dc, true);
493 }
494
495 void wxGenericColourDialog::OnCustomColourClick(int which)
496 {
497 wxClientDC dc(this);
498 PaintHighlight(dc, false);
499 whichKind = 2;
500 colourSelection = which;
501
502 #if wxUSE_SLIDER
503 redSlider->SetValue( customColours[colourSelection].Red() );
504 greenSlider->SetValue( customColours[colourSelection].Green() );
505 blueSlider->SetValue( customColours[colourSelection].Blue() );
506 #endif // wxUSE_SLIDER
507
508 colourData.m_dataColour.Set(customColours[colourSelection].Red(),
509 customColours[colourSelection].Green(),
510 customColours[colourSelection].Blue());
511
512 PaintCustomColour(dc);
513 PaintHighlight(dc, true);
514 }
515
516 /*
517 void wxGenericColourDialog::OnOk(void)
518 {
519 Show(false);
520 }
521
522 void wxGenericColourDialog::OnCancel(void)
523 {
524 colourDialogCancelled = true;
525 Show(false);
526 }
527 */
528
529 void wxGenericColourDialog::OnAddCustom(wxCommandEvent& WXUNUSED(event))
530 {
531 wxClientDC dc(this);
532 if (whichKind != 2)
533 {
534 PaintHighlight(dc, false);
535 whichKind = 2;
536 colourSelection = 0;
537 PaintHighlight(dc, true);
538 }
539
540 customColours[colourSelection].Set(colourData.m_dataColour.Red(),
541 colourData.m_dataColour.Green(),
542 colourData.m_dataColour.Blue());
543
544 colourData.SetCustomColour(colourSelection, customColours[colourSelection]);
545
546 PaintCustomColours(dc);
547 }
548
549 #if wxUSE_SLIDER
550
551 void wxGenericColourDialog::OnRedSlider(wxCommandEvent& WXUNUSED(event))
552 {
553 if (!redSlider)
554 return;
555
556 wxClientDC dc(this);
557 colourData.m_dataColour.Set((unsigned char)redSlider->GetValue(), colourData.m_dataColour.Green(), colourData.m_dataColour.Blue());
558 PaintCustomColour(dc);
559 }
560
561 void wxGenericColourDialog::OnGreenSlider(wxCommandEvent& WXUNUSED(event))
562 {
563 if (!greenSlider)
564 return;
565
566 wxClientDC dc(this);
567 colourData.m_dataColour.Set(colourData.m_dataColour.Red(), (unsigned char)greenSlider->GetValue(), colourData.m_dataColour.Blue());
568 PaintCustomColour(dc);
569 }
570
571 void wxGenericColourDialog::OnBlueSlider(wxCommandEvent& WXUNUSED(event))
572 {
573 if (!blueSlider)
574 return;
575
576 wxClientDC dc(this);
577 colourData.m_dataColour.Set(colourData.m_dataColour.Red(), colourData.m_dataColour.Green(), (unsigned char)blueSlider->GetValue());
578 PaintCustomColour(dc);
579 }
580
581 #endif // wxUSE_SLIDER
582
583 #endif // wxUSE_COLOURDLG && !defined(__WXGTK20__)