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