1 // PaletteLayoutDlg.cpp : implementation file
2 //
3 
4 #include "stdafx.h"
5 #include "afxdialogex.h"
6 #include "express_table_row.h"
7 #include "PaletteLayoutDlg.h"
8 
9 extern CString target_class_name;
10 
11 enum CONTROL_IDS {
12     ID_REDFIELD = 4096,
13     ID_GREENFIELD,
14     ID_BLUEFIELD,
15     ID_ALPHAFIELD,
16     ID_PAL_INDEX
17 };
18 
19 enum palette_layout_dlg_test_commands{
20     TEST_SET_PREDEFINED_PALETTE_ENTRY = 1,
21     TEST_SET_PALETTE_COLOR,
22     TEST_SAVE_PALETTE_EDIT,
23     TEST_CANCEL_PALETTE_EDIT
24 };
25 
26 // PaletteLayoutDlg dialog
BEGIN_MESSAGE_MAP(PaletteLayoutDlg,express_dialog)27 BEGIN_MESSAGE_MAP(PaletteLayoutDlg, express_dialog)
28     //ON_BN_CLICKED(IDC_BROWSE_PATH, &NewProjectDlg::OnBnClickedBrowsePath)
29     //ON_BN_CLICKED(ID_CANCEL, &NewProjectDlg::OnCancel)
30     ON_WM_SHOWWINDOW()
31     ON_WM_SYSCHAR()
32     ON_WM_PAINT()
33     ON_WM_VSCROLL()
34     ON_COMMAND(IDOK, &PaletteLayoutDlg::OnReturnKey)
35 
36     ON_BN_CLICKED(IDOK, &PaletteLayoutDlg::OnBnClickedOk)
37     ON_BN_CLICKED(IDCANCEL,  &PaletteLayoutDlg::OnCancel)
38     ON_BN_CLICKED(IDCANCEL, &PaletteLayoutDlg::OnCancel)
39     ON_BN_CLICKED(IDC_IMPORT_PALETTE, &PaletteLayoutDlg::OnBnClickedImportPalette)
40     ON_BN_CLICKED(IDC_EXPORT_PALETTE, &PaletteLayoutDlg::OnBnClickedExportPalette)
41     ON_BN_CLICKED(IDC_DEFAULT_PALETTE, &PaletteLayoutDlg::OnBnClickedDefaultPalette)
42 
43     ON_EN_KILLFOCUS(IDC_TOTAL_PALETTE_ENTRIES, &PaletteLayoutDlg::OnEnChangeTotalPaletteEntries)
44     ON_EN_KILLFOCUS(IDC_USER_PALETTE_ENTRIES, &PaletteLayoutDlg::OnEnChangeUserPaletteEntries)
45     ON_MESSAGE(STUDIO_TEST, &PaletteLayoutDlg::OnTestMessage)
46     ON_BN_CLICKED(IDC_GEN_GRADIENT, &PaletteLayoutDlg::OnGenGradient)
47 END_MESSAGE_MAP()
48 
49 ///////////////////////////////////////////////////////////////////////////////
50 PaletteLayoutDlg::PaletteLayoutDlg(int display, int theme, CWnd* pParent /*=NULL*/)
51 	: express_dialog(PaletteLayoutDlg::IDD, pParent)
52 {
53     IconId = IDB_RECENT_PROJECT;
54     SetTitleText("Edit Palette");
55 
56     mDisplay = display;
57     mTheme = theme;
58     mpProject = GetOpenProject();
59     mPaletteResetToDefault = FALSE;
60     mpPaletteFrame = NULL;
61 
62     // save current settings in case user cancels after making changes:
63 
64     if (!mpProject->mDisplays[mDisplay].themes[mTheme].palette)
65     {
66         //create default palette
67         ProjectConfigDlg::CreateDefaultPalette(mpProject, mDisplay, mTheme);
68     }
69 
70     if (mpProject->mDisplays[mDisplay].themes[mTheme].palette)
71     {
72         theme_info* tinfo = &mpProject->mDisplays[mDisplay].themes[mTheme];
73         old_pal_total_entries = tinfo->palette_total_size;
74         old_pal_predefined = tinfo->palette_predefined;
75         memcpy_s(OldPalette, sizeof(OldPalette), tinfo->palette, tinfo->palette_total_size * sizeof(GX_COLOR));
76     }
77 }
78 
79 ///////////////////////////////////////////////////////////////////////////////
~PaletteLayoutDlg()80 PaletteLayoutDlg::~PaletteLayoutDlg()
81 {
82     if (mpPaletteFrame)
83     {
84         delete mpPaletteFrame;
85     }
86 }
87 
88 
89 ///////////////////////////////////////////////////////////////////////////////
OnInitDialog()90 BOOL PaletteLayoutDlg::OnInitDialog()
91 {
92     express_dialog::OnInitDialog();
93 
94     // TODO:  Add extra initialization here
95     CRect client;
96     CRect size;
97     CRect scrollsize;
98 
99     GetClientRect(&client);
100 
101     // Get palette scroll bar size
102     GetDlgItem(IDC_PALETTE_SCROLL)->GetWindowRect(&scrollsize);
103     ScreenToClient(&scrollsize);
104 
105     client.left += 10;
106     client.top = scrollsize.top;
107     client.right = scrollsize.left - 5;
108     client.bottom = scrollsize.bottom;
109 
110     // Create palette frame
111     mpPaletteFrame = new palette_frame(&mpProject->mDisplays[mDisplay].themes[mTheme]);
112     mpPaletteFrame->Create(target_class_name, _T("PaletteFrame"), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_TABSTOP, client, this, 0, NULL);
113 
114     AddCancelButton();
115     AddSaveButton();
116 
117     return TRUE;  // return TRUE unless you set the focus to a control
118     // EXCEPTION: OCX Property Pages should return FALSE
119 }
120 
121 ///////////////////////////////////////////////////////////////////////////////
OnShowWindow(BOOL bShow,UINT nStatus)122 void PaletteLayoutDlg::OnShowWindow(BOOL bShow, UINT nStatus)
123 {
124     express_dialog::OnShowWindow(bShow, nStatus);
125 }
126 
127 ///////////////////////////////////////////////////////////////////////////////
NotifyColorChanged(int index,GX_COLOR newcolor)128 void PaletteLayoutDlg::NotifyColorChanged(int index, GX_COLOR newcolor)
129 {
130     if (index < mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined)
131     {
132         mpProject->mDisplays[mDisplay].themes[mTheme].palette[index] = newcolor;
133         mpProject->SetModified();
134     }
135 }
136 
137 ///////////////////////////////////////////////////////////////////////////////
OnPaint()138 void PaletteLayoutDlg::OnPaint()
139 {
140     express_dialog::OnPaint();
141 }
142 
143 ///////////////////////////////////////////////////////////////////////////////
DoDataExchange(CDataExchange * pDX)144 void PaletteLayoutDlg::DoDataExchange(CDataExchange* pDX)
145 {
146     int auto_entries;
147 
148     CDialog::DoDataExchange(pDX);
149     DDX_Text(pDX, IDC_THEME_NAME, mpProject->mDisplays[mDisplay].themes[mTheme].theme_name);
150     DDX_Text(pDX, IDC_TOTAL_PALETTE_ENTRIES, mpProject->mDisplays[mDisplay].themes[mTheme].palette_total_size);
151     DDX_Text(pDX, IDC_USER_PALETTE_ENTRIES, mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined);
152 
153     auto_entries = mpProject->mDisplays[mDisplay].themes[mTheme].palette_total_size - mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined;
154     DDX_Text(pDX, IDC_AUTO_PALETTE_ENTRIES, auto_entries);
155     DDX_Control(pDX, IDC_PALETTE_SCROLL, mPalIndexScroll);
156 
157     SCROLLINFO info;
158     info.fMask = SIF_RANGE|SIF_POS|SIF_PAGE;
159     info.nMin = 0;
160     info.nMax = 255;
161     info.nPage = VISIBLE_PALETTE_ROWS;
162     info.nPos = 0;
163 
164     mPalIndexScroll.SetScrollInfo(&info);
165 }
166 
167 ///////////////////////////////////////////////////////////////////////////////
OnReturnKey()168 void PaletteLayoutDlg::OnReturnKey()
169 {
170     CWnd *pctrl = GetFocus();
171     int ctrl_id = pctrl->GetDlgCtrlID();
172 
173     switch(ctrl_id)
174     {
175     case IDC_TOTAL_PALETTE_ENTRIES:
176         OnEnChangeTotalPaletteEntries();
177         break;
178 
179     case IDC_USER_PALETTE_ENTRIES:
180         OnEnChangeUserPaletteEntries();
181         break;
182 
183     case IDOK:
184         OnBnClickedOk();
185         break;
186     }
187     return;
188 }
189 
190 ///////////////////////////////////////////////////////////////////////////////
191 /* go throught the color resources in this theme, and if any of the colors
192    have an index larger than palette pre-defined size, reset that color index to
193    the best match. This function is called when the user reduces the pre-defined
194    palette size.
195 */
CheckResetColorIndexes(res_info * info,GX_COLOR * new_palette,USHORT new_pal_size)196 void PaletteLayoutDlg::CheckResetColorIndexes(res_info *info, GX_COLOR *new_palette, USHORT new_pal_size)
197 {
198     while(info)
199     {
200         if (info->type == RES_TYPE_COLOR)
201         {
202             if (info->colorval >= new_pal_size)
203             {
204                 if (info->colorval < (ULONG) old_pal_predefined)
205                 {
206                     Pixel old_color(OldPalette[info->colorval]);
207                     info->colorval = image_reader::GetNearestPaletteColor(old_color, new_palette, new_pal_size);
208                 }
209                 else
210                 {
211                     info->colorval = 0;
212                 }
213             }
214         }
215         if (info->child)
216         {
217             CheckResetColorIndexes(info->child, new_palette, new_pal_size);
218         }
219         info = info->next;
220     }
221 }
222 
223 ///////////////////////////////////////////////////////////////////////////////
224 // PaletteLayoutDlg message handlers
225 ///////////////////////////////////////////////////////////////////////////////
OnBnClickedOk()226 void PaletteLayoutDlg::OnBnClickedOk()
227 {
228     studiox_project *project = GetOpenProject();
229 
230     if (project)
231     {
232         if (mPaletteResetToDefault)
233         {
234             // Remap colors to the best match in the new color palette.
235             ProjectConfigDlg::ColorTableConvert(mpProject->mDisplays[mDisplay].themes[mTheme].GetFirstResourceInfo(),
236                                     OldPalette,
237                                     old_pal_predefined,
238                                     mpProject->mDisplays[mDisplay].colorformat,
239                                     mpProject->mDisplays[mDisplay].themes[mTheme].palette,
240                                     mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined,
241                                     mpProject->mDisplays[mDisplay].colorformat);
242         }
243         else
244         {
245             /* If any of the color resources are using an index greater than the
246                number of pre-defined entried, remap that entry of the color table
247             */
248 
249             int new_pal_size = mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined;
250             if (new_pal_size < old_pal_predefined)
251             {
252                 CheckResetColorIndexes(project->mDisplays[mDisplay].themes[mTheme].GetFirstResourceInfo(),
253                                        mpProject->mDisplays[mDisplay].themes[mTheme].palette, new_pal_size);
254             }
255         }
256 
257         /* If we are running in palette mode, we need to remap the color resources to the
258            new palette
259         */
260         project->InitializeAllPixelmaps();
261         GetResourceView()->OnDisplaySelect(GetProjectView()->GetActiveDisplay(), TRUE);
262     }
263 
264     CDialog::OnOK();
265 }
266 
267 
268 ///////////////////////////////////////////////////////////////////////////////
OnCancel()269 void PaletteLayoutDlg::OnCancel()
270 {
271     // TODO: Add your control notification handler code here
272 
273     // restore palette settings:
274 
275     if (mpProject->mDisplays[mDisplay].themes[mTheme].palette)
276     {
277         theme_info* tinfo = &mpProject->mDisplays[mDisplay].themes[mTheme];
278         tinfo->palette_total_size = old_pal_total_entries;
279         tinfo->palette_predefined = old_pal_predefined;
280         memcpy_s(tinfo->palette, tinfo->palette_total_size * sizeof(GX_COLOR), OldPalette, sizeof(OldPalette));
281         mPaletteResetToDefault = FALSE;
282     }
283     CDialog::OnCancel();
284 }
285 
286 ///////////////////////////////////////////////////////////////////////////////
OnEnChangeTotalPaletteEntries()287 void PaletteLayoutDlg::OnEnChangeTotalPaletteEntries()
288 {
289     int newval = GetDlgItemInt(IDC_TOTAL_PALETTE_ENTRIES, NULL, TRUE);
290 
291     if (newval >= 2 && newval <= 256)
292     {
293         mpProject->mDisplays[mDisplay].themes[mTheme].palette_total_size = newval;
294 
295         // check to see if we need to update pre-defined count
296         if (mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined >= newval)
297         {
298             mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined = newval - 1;
299             SetDlgItemInt(IDC_USER_PALETTE_ENTRIES, mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined);
300         }
301 
302         // update the leftover count
303         int autocount = newval - mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined;
304         SetDlgItemInt(IDC_AUTO_PALETTE_ENTRIES, autocount);
305         mpProject->SetModified();
306     }
307     else
308     {
309         ErrorMsg("The palette total size must be between 2 and 256 entries.", this);
310         SetDlgItemInt(IDC_TOTAL_PALETTE_ENTRIES, mpProject->mDisplays[mDisplay].themes[mTheme].palette_total_size);
311     }
312 }
313 
314 
315 ///////////////////////////////////////////////////////////////////////////////
OnEnChangeUserPaletteEntries()316 void PaletteLayoutDlg::OnEnChangeUserPaletteEntries()
317 {
318     int totalcount = mpProject->mDisplays[mDisplay].themes[mTheme].palette_total_size;
319     int usercount = GetDlgItemInt(IDC_USER_PALETTE_ENTRIES, NULL, TRUE);
320 
321     if (usercount >= 0 && usercount < totalcount)
322     {
323         int old_usercount = mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined;
324 
325         mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined = usercount;
326 
327         // update the leftover count
328         int autocount = totalcount - usercount;
329         SetDlgItemInt(IDC_AUTO_PALETTE_ENTRIES, autocount);
330         mpProject->SetModified();
331 
332         for (int index = old_usercount; index < usercount; index++)
333         {
334             //initiate new added entries
335             mpProject->mDisplays[mDisplay].themes[mTheme].palette[index] = 0xff000000;
336         }
337 
338         mpPaletteFrame->SetRowData();
339     }
340     else
341     {
342         ErrorMsg("The pre-defined palette entries must be between 1 and (total palette size - 1).", this);
343         SetDlgItemInt(IDC_USER_PALETTE_ENTRIES, mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined);
344     }
345 }
346 
347 
348 ///////////////////////////////////////////////////////////////////////////////
OnBnClickedImportPalette()349 void PaletteLayoutDlg::OnBnClickedImportPalette()
350 {
351     // TODO: Add your control notification handler code here
352     CString Pathname;
353     int count;
354     int index;
355 
356     if (BrowseForSingleFile(_T("Select Palette File"),
357         _T("Palette Files\0*.palx\0\0"), _T("palx"), Pathname, this))
358     {
359         xml_reader reader;
360 
361         if (!reader.ReadFile(CString(Pathname)))
362         {
363             ErrorMsg("Unable to read palette file", this);
364             return;
365         }
366 
367         if (!reader.EnterSection("GUIX_Palette"))
368         {
369             ErrorMsg("Invalid palette file format", this);
370             return;
371         }
372         reader.ReadInt("total_entries", mpProject->mDisplays[mDisplay].themes[mTheme].palette_total_size);
373         reader.ReadInt("user_entries", count);
374         mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined = count;
375 
376         if (!mpProject->mDisplays[mDisplay].themes[mTheme].palette)
377         {
378             mpProject->mDisplays[mDisplay].themes[mTheme].palette = new GX_COLOR[256];
379         }
380 
381         for (index = 0; index < count; index++)
382         {
383             reader.ReadHex("rgb", mpProject->mDisplays[mDisplay].themes[mTheme].palette[index]);
384         }
385         reader.CloseSection();
386 
387         int totalcount = mpProject->mDisplays[mDisplay].themes[mTheme].palette_total_size;
388         int usercount = mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined;
389 
390         SetDlgItemInt(IDC_TOTAL_PALETTE_ENTRIES, totalcount);
391         SetDlgItemInt(IDC_USER_PALETTE_ENTRIES, usercount);
392         int autocount = totalcount - usercount;
393         SetDlgItemInt(IDC_AUTO_PALETTE_ENTRIES, autocount);
394 
395         mpPaletteFrame->SetRowData();
396         mpProject->SetModified();
397     }
398 }
399 
400 
401 ///////////////////////////////////////////////////////////////////////////////
OnBnClickedExportPalette()402 void PaletteLayoutDlg::OnBnClickedExportPalette()
403 {
404     // TODO: Add your control notification handler code here
405     TCHAR SavePathname[MAX_PATH];
406     TCHAR FileName[MAX_PATH];
407     int count;
408     int index;
409 
410     SavePathname[0] = 0;
411     FileName[0] = 0;
412 
413     if (GetOutputFileName(SavePathname, FileName,
414             _T("Select Palette Output file"),
415             _T("Palette Files\0*.palx\0\0"),
416             NULL, _T("palx")), this)
417     {
418         xml_writer writer;
419 
420         if (!writer.OpenFile(CString(SavePathname)))
421         {
422             ErrorMsg("Unable to write palette file", this);
423             return;
424         }
425 
426         writer.WriteHeader("GUIX_Palette");
427         writer.OpenTag("GUIX_Palette");
428         writer.WriteInt("total_entries", mpProject->mDisplays[mDisplay].themes[mTheme].palette_total_size);
429 
430         count = mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined;
431         writer.WriteInt("user_entries", count);
432 
433         for (index = 0; index < count; index++)
434         {
435             writer.WriteHex("rgb", mpProject->mDisplays[mDisplay].themes[mTheme].palette[index]);
436         }
437         writer.CloseTag("GUIX_Palette");
438         writer.CloseFile();
439     }
440 }
441 
442 
443 
444 ///////////////////////////////////////////////////////////////////////////////
OnBnClickedDefaultPalette()445 void PaletteLayoutDlg::OnBnClickedDefaultPalette()
446 {
447     // TODO: Add your control notification handler code here
448     ProjectConfigDlg::CreateDefaultPalette(mpProject, mDisplay, mTheme);
449 
450     mPaletteResetToDefault = TRUE;
451 
452     mpProject->SetModified();
453 
454     int totalcount = mpProject->mDisplays[mDisplay].themes[mTheme].palette_total_size;
455     int usercount = mpProject->mDisplays[mDisplay].themes[mTheme].palette_predefined;
456 
457     SetDlgItemInt(IDC_TOTAL_PALETTE_ENTRIES, totalcount);
458     SetDlgItemInt(IDC_USER_PALETTE_ENTRIES, usercount);
459     int autocount = totalcount - usercount;
460     SetDlgItemInt(IDC_AUTO_PALETTE_ENTRIES, autocount);
461 
462     mpPaletteFrame->SetRowData();
463 }
464 
465 ///////////////////////////////////////////////////////////////////////////////
OnGenGradient()466 void PaletteLayoutDlg::OnGenGradient()
467 {
468     INT start_index, end_index;
469     theme_info *theme = &mpProject->mDisplays[mDisplay].themes[mTheme];
470 
471     start_index = GetDlgItemInt(IDC_START_INDEX);
472     end_index = GetDlgItemInt(IDC_END_INDEX);
473 
474     if (start_index < 0)
475     {
476         start_index = 0;
477     }
478 
479     if (end_index > theme->palette_predefined - 1)
480     {
481         end_index = theme->palette_predefined - 1;
482     }
483 
484     if (start_index < end_index)
485     {
486         int bcolor, balpha, bred, bgreen, bblue;
487         int fcolor, falpha, fred, fgreen, fblue;
488         int ncolor, nalpha, nred, ngreen, nblue;
489         int count = end_index - start_index;
490 
491         //pick start color
492         fcolor = theme->palette[start_index];
493 
494         //pick end color
495         bcolor = theme->palette[end_index];
496 
497         falpha = (fcolor >> 24) & 0xff;
498         fred = (unsigned char)(fcolor >> 16);
499         fgreen = (fcolor >> 8) & 0xff;
500         fblue = fcolor & 0xff;
501 
502         balpha = (bcolor >> 24) & 0xff;
503         bred = (unsigned char)(bcolor >> 16);
504         bgreen = (bcolor >> 8) & 0xff;
505         bblue = bcolor & 0xff;
506 
507         start_index++;
508 
509         for (int index = 1; index < count; index++)
510         {
511             //gen gradient color
512             nalpha = (((balpha - falpha) * index) / count) + falpha;
513             nred = (((bred - fred) * index) / count) + fred;
514             nblue = (((bblue - fblue) * index) / count) + fblue;
515             ngreen = (((bgreen - fgreen) * index) / count) + fgreen;
516             ncolor = (nalpha << 24) | (nred << 16) | (ngreen << 8) | nblue;
517 
518             theme->palette[start_index++] = ncolor;
519         }
520 
521         mpPaletteFrame->SetRowData();
522     }
523 }
524 
Scroll(int deltaPos)525 void PaletteLayoutDlg::Scroll(int deltaPos)
526 {
527     int top_index = mpPaletteFrame->GetTopIndex();
528 
529     if (deltaPos != 0)
530     {
531         // Compute the new scroll position.
532         top_index += deltaPos;
533 
534         if (top_index < 0)
535         {
536             top_index = 0;
537         }
538         else
539         {
540             if (top_index + VISIBLE_PALETTE_ROWS > 256)
541             {
542                 top_index = 256 - VISIBLE_PALETTE_ROWS;
543             }
544         }
545         if (top_index != mpPaletteFrame->GetTopIndex())
546         {
547             mpPaletteFrame->SetTopIndex(top_index);
548             ::SetScrollPos(mPalIndexScroll.GetSafeHwnd(), SB_CTL, top_index, TRUE);
549             mpPaletteFrame->SetRowData();
550         }
551     }
552 }
553 
554 ///////////////////////////////////////////////////////////////////////////////
OnVScroll(UINT nSBCode,UINT nPos,CScrollBar * bar)555 void PaletteLayoutDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *bar)
556 {
557     int deltaPos = 0;
558     int top_index = mpPaletteFrame->GetTopIndex();
559 
560     switch( nSBCode )
561     {
562     case SB_LINEUP:
563         // Up arrow button on scrollbar was pressed.
564         deltaPos = -1;
565         break;
566 
567     case SB_LINEDOWN:
568         // Down arrow button on scrollbar was pressed.
569         deltaPos = 1;
570         break;
571 
572     case SB_PAGEUP:
573         // User clicked inbetween up arrow and thumb.
574         deltaPos = -VISIBLE_PALETTE_ROWS;
575         break;
576 
577     case SB_PAGEDOWN:
578         // User clicked inbetween thumb and down arrow.
579         deltaPos = VISIBLE_PALETTE_ROWS;
580         break;
581 
582     case SB_THUMBTRACK:
583         // Scrollbar thumb is being dragged.
584         deltaPos = nPos - top_index;
585         break;
586 
587     case SB_THUMBPOSITION:
588         // Scrollbar thumb was released.
589         deltaPos = nPos - top_index;
590         break;
591 
592     default:
593         // We don't process other scrollbar messages.
594         return;
595     }
596 
597     // Scroll the window if needed.
598     Scroll(deltaPos);
599 }
600 
601 ///////////////////////////////////////////////////////////////////////////////
OnTestMessage(WPARAM wParam,LPARAM lParam)602 LRESULT PaletteLayoutDlg::OnTestMessage(WPARAM wParam, LPARAM lParam)
603 {
604     CString text;
605     CWnd *pWnd;
606     int index;
607     GX_COLOR color;
608     CStringArray strlist;
609 
610     switch (wParam)
611     {
612     case TEST_SET_PREDEFINED_PALETTE_ENTRY:
613         pWnd = GetDlgItem(IDC_USER_PALETTE_ENTRIES);
614 
615         if (pWnd)
616         {
617             text.Format(_T("%d"), lParam);
618             pWnd->SetWindowText(text);
619             SendMessage(WM_COMMAND, MAKEWPARAM(IDC_USER_PALETTE_ENTRIES, EN_KILLFOCUS), (LPARAM)pWnd->m_hWnd);
620         }
621         break;
622 
623     case TEST_SET_PALETTE_COLOR:
624         SplitString(GetTestingParam(0), ',', &strlist);
625         index = _tstoi(strlist.GetAt(0));
626         color = _tstoi(strlist.GetAt(1));
627         NotifyColorChanged(index, color);
628         break;
629 
630     case TEST_SAVE_PALETTE_EDIT:
631         OnOK();
632         break;
633 
634     case TEST_CANCEL_PALETTE_EDIT:
635         OnCancel();
636         break;
637     }
638 
639     return 0;
640 }
641 
BEGIN_MESSAGE_MAP(palette_row,express_table_row)642 BEGIN_MESSAGE_MAP(palette_row, express_table_row)
643 	ON_WM_PAINT()
644     ON_WM_CREATE()
645     ON_WM_ERASEBKGND()
646     ON_EN_KILLFOCUS(ID_REDFIELD, palette_row::ColorChanged)
647     ON_EN_KILLFOCUS(ID_GREENFIELD, palette_row::ColorChanged)
648     ON_EN_KILLFOCUS(ID_BLUEFIELD, palette_row::ColorChanged)
649     ON_EN_KILLFOCUS(ID_ALPHAFIELD, palette_row::ColorChanged)
650 END_MESSAGE_MAP()
651 
652 
653 ///////////////////////////////////////////////////////////////////////////////
654 palette_row::palette_row()
655 {
656     mIndex = -1;
657 }
658 
659 ///////////////////////////////////////////////////////////////////////////////
OnCreate(LPCREATESTRUCT lpCreateStruct)660 int palette_row::OnCreate(LPCREATESTRUCT lpCreateStruct)
661 {
662     express_table_row::OnCreate(lpCreateStruct);
663     CRect client;
664     CRect size;
665 
666     GetClientRect(&client);
667 
668     int offset = client.Width() / 8;
669     size = client;
670     size.top += 4;
671     size.bottom -= 4;
672     size.left += 5;
673     size.right = offset - 10;
674     mIndexPrompt.Create(_T("--"), WS_CHILD | SS_CENTER | WS_VISIBLE, size, this, ID_PAL_INDEX);
675 
676     size.left = offset * 4 + 5;
677     size.right = size.left + offset - 5;
678     mAlphaField.Create(WS_CHILD | SS_RIGHT | WS_VISIBLE | ES_NUMBER | WS_BORDER | WS_TABSTOP, size, this, ID_ALPHAFIELD);
679     SetAccessibleDescription(mAlphaField.GetSafeHwnd(), L"Use arrow keys to navigate.");
680     SetAccessibleFullDescription(mAlphaField.GetSafeHwnd(), L"Use arrow keys to navigate.");
681 
682     size.OffsetRect(offset, 0);
683     mRedField.Create(WS_CHILD|SS_RIGHT|WS_VISIBLE|ES_NUMBER|WS_BORDER | WS_TABSTOP, size, this, ID_REDFIELD);
684     SetAccessibleDescription(mRedField.GetSafeHwnd(), L"Use arrow keys to navigate.");
685     SetAccessibleFullDescription(mRedField.GetSafeHwnd(), L"Use arrow keys to navigate.");
686 
687     size.OffsetRect(offset, 0);
688     mGreenField.Create(WS_CHILD|SS_RIGHT|WS_VISIBLE|ES_NUMBER|WS_BORDER | WS_TABSTOP, size, this, ID_GREENFIELD);
689     SetAccessibleDescription(mGreenField.GetSafeHwnd(), L"Use arrow keys to navigate.");
690     SetAccessibleFullDescription(mGreenField.GetSafeHwnd(), L"Use arrow keys to navigate.");
691 
692     size.OffsetRect(offset, 0);
693     mBlueField.Create(WS_CHILD|SS_RIGHT|WS_VISIBLE|ES_NUMBER|WS_BORDER | WS_TABSTOP, size, this, ID_BLUEFIELD);
694     SetAccessibleDescription(mBlueField.GetSafeHwnd(), L"Use arrow keys to navigate.");
695     SetAccessibleFullDescription(mBlueField.GetSafeHwnd(), L"Use arrow keys to navigate.");
696     return 0;
697 }
698 
699 
700 ///////////////////////////////////////////////////////////////////////////////
SetData(int index,GX_COLOR color,BOOL Enabled)701 void palette_row::SetData(int index, GX_COLOR color, BOOL Enabled)
702 {
703     CEdit *edit;
704 
705     if (mIndex != index)
706     {
707         CString acc_name;
708 
709         // set accessible names
710         acc_name.Format(_T("alpha %d"), index);
711         SetControlAccessibleName(GetDlgItem(ID_ALPHAFIELD)->GetSafeHwnd(), acc_name.GetString());
712 
713         acc_name.Format(_T("red %d"), index);
714         SetControlAccessibleName(GetDlgItem(ID_REDFIELD)->GetSafeHwnd(), acc_name.GetString());
715 
716         acc_name.Format(_T("green %d"), index);
717         SetControlAccessibleName(GetDlgItem(ID_GREENFIELD)->GetSafeHwnd(), acc_name.GetString());
718 
719         acc_name.Format(_T("blue %d"), index);
720         SetControlAccessibleName(GetDlgItem(ID_BLUEFIELD)->GetSafeHwnd(), acc_name.GetString());
721 
722         mIndex = index;
723     }
724 
725     mColor = color;
726     mEnabled = Enabled;
727 
728     SetDlgItemInt(ID_PAL_INDEX, index);
729 
730     if (Enabled)
731     {
732         mAlpha = (color >> 24) & 0xff;
733         SetDlgItemInt(ID_ALPHAFIELD, mAlpha);
734 
735         mRed = (unsigned char) (color >> 16);
736         SetDlgItemInt(ID_REDFIELD, mRed);
737 
738         mGreen = (color >> 8) & 0xff;
739         SetDlgItemInt(ID_GREENFIELD, mGreen);
740 
741         mBlue = color & 0xff;
742         SetDlgItemInt(ID_BLUEFIELD, mBlue);
743 
744         edit = (CEdit *)GetDlgItem(ID_ALPHAFIELD);
745         edit->SetReadOnly(FALSE);
746         edit = (CEdit *) GetDlgItem(ID_REDFIELD);
747         edit->SetReadOnly(FALSE);
748         edit = (CEdit *) GetDlgItem(ID_GREENFIELD);
749         edit->SetReadOnly(FALSE);
750         edit = (CEdit *) GetDlgItem(ID_BLUEFIELD);
751         edit->SetReadOnly(FALSE);
752     }
753     else
754     {
755         SetDlgItemText(ID_ALPHAFIELD, _T("- - "));
756         SetDlgItemText(ID_REDFIELD, _T("- - "));
757         SetDlgItemText(ID_GREENFIELD, _T("- - "));
758         SetDlgItemText(ID_BLUEFIELD, _T("- - "));
759         edit = (CEdit *)GetDlgItem(ID_ALPHAFIELD);
760         edit->SetReadOnly();
761         edit = (CEdit *) GetDlgItem(ID_REDFIELD);
762         edit->SetReadOnly();
763         edit = (CEdit *) GetDlgItem(ID_GREENFIELD);
764         edit->SetReadOnly();
765         edit = (CEdit *) GetDlgItem(ID_BLUEFIELD);
766         edit->SetReadOnly();
767     }
768     Invalidate();
769 }
770 
771 
772 ///////////////////////////////////////////////////////////////////////////////
OnPaint()773 void palette_row::OnPaint()
774 {
775     CBrush boxbrush;
776    // CBrush *old_brush;
777     CRect boxsize;
778     CPaintDC dc(this);
779     express_table_row::OnPaint();
780 
781     GetClientRect(&boxsize);
782     int offset = boxsize.Width() / 8;
783     boxsize.left  = offset + 10;
784     boxsize.right = offset * 4 - 10;
785     boxsize.top += 5;
786     boxsize.bottom -= 5;
787 
788     if (mEnabled)
789     {
790         boxbrush.CreateSolidBrush(RGB(mRed, mGreen, mBlue));
791     }
792     else
793     {
794         boxbrush.CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0));
795     }
796     //old_brush = dc->SelectObject(&boxbrush);
797 
798     dc.FillRect(&boxsize, &boxbrush);
799 }
800 
801 ///////////////////////////////////////////////////////////////////////////////
OnEraseBkgnd(CDC * pDC)802 BOOL palette_row::OnEraseBkgnd(CDC* pDC)
803 {
804     CBrush evenBrush(RGB(210, 210, 210));
805     CBrush oddBrush(RGB(190, 190, 190));
806     CBrush *pOldBrush;
807 
808     if (mIndex & 1)
809     {
810         pOldBrush = pDC->SelectObject(&oddBrush);
811     }
812     else
813     {
814         pOldBrush = pDC->SelectObject(&evenBrush);
815     }
816     CRect rect;
817     pDC->GetClipBox(&rect);     // Erase the area needed
818 
819     pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),
820         PATCOPY);
821     pDC->SelectObject(pOldBrush);
822     return TRUE;
823 }
824 
825 ///////////////////////////////////////////////////////////////////////////////
ColorChanged()826 void palette_row::ColorChanged()
827 {
828     BOOL changed = FALSE;
829     int val = GetDlgItemInt(ID_ALPHAFIELD);
830     if (val < 0 || val > 255)
831     {
832         SetDlgItemInt(ID_ALPHAFIELD, mAlpha);
833     }
834     else
835     {
836         mAlpha = val;
837         changed = TRUE;
838     }
839 
840     val = GetDlgItemInt(ID_REDFIELD);
841     if (val < 0 || val > 255)
842     {
843         SetDlgItemInt(ID_REDFIELD, mRed);
844     }
845     else
846     {
847         mRed = val;
848         changed = TRUE;
849     }
850 
851     val = GetDlgItemInt(ID_GREENFIELD);
852     if (val < 0 || val > 255)
853     {
854         SetDlgItemInt(ID_GREENFIELD, mGreen);
855     }
856     else
857     {
858         mGreen = val;
859         changed = TRUE;
860     }
861     val = GetDlgItemInt(ID_BLUEFIELD);
862     if (val < 0 || val > 255)
863     {
864         SetDlgItemInt(ID_BLUEFIELD, mBlue);
865     }
866     else
867     {
868         mBlue = val;
869         changed = TRUE;
870     }
871 
872     if (changed)
873     {
874         mColor = (mAlpha << 24) | (mRed << 16) | (mGreen << 8) | mBlue;
875 
876         palette_frame *win = (palette_frame*) GetParent();
877         win->NotifyColorChanged(mIndex, mColor);
878         Invalidate();   // force repaint color swatch
879     }
880 }
881 
882 ///////////////////////////////////////////////////////////////////////////////
PreTranslateMessage(MSG * pMsg)883 BOOL palette_row::PreTranslateMessage(MSG *pMsg)
884 {
885     if (pMsg->message == WM_KEYDOWN)
886     {
887         CWnd* focus_owner = GetFocus();
888         CWnd* next_focus_owner = NULL;
889         palette_frame *frame = (palette_frame*)GetParent();
890 
891         switch (pMsg->wParam)
892         {
893         case VK_RETURN:
894             ColorChanged();
895             break;
896 
897         case VK_LEFT:
898         case VK_RIGHT:
899             next_focus_owner = GetNextTabStopChild(focus_owner, pMsg->wParam);
900             break;
901 
902         case VK_UP:
903             next_focus_owner = GetNextTabStopChild(focus_owner, pMsg->wParam);
904             if (!next_focus_owner)
905             {
906                 if (frame->GetTopIndex() > 0)
907                 {
908                     frame->Scroll(-1);
909                 }
910                 next_focus_owner = focus_owner;
911             }
912             break;
913 
914         case VK_DOWN:
915             next_focus_owner = GetNextTabStopChild(focus_owner, pMsg->wParam);
916             if (!next_focus_owner)
917             {
918                 if (frame->GetTopIndex() < 256 - VISIBLE_PALETTE_ROWS)
919                 {
920                     frame->Scroll(1);
921                 }
922                 next_focus_owner = focus_owner;
923             }
924             break;
925 
926         case VK_HOME:
927             next_focus_owner = GetNextTabStopChild(focus_owner, pMsg->wParam);
928             if (frame->GetTopIndex() > 0)
929             {
930                 frame->Scroll(-frame->GetTopIndex());
931             }
932             break;
933 
934         case VK_END:
935             next_focus_owner = GetNextTabStopChild(focus_owner, pMsg->wParam);
936             if (frame->GetTopIndex() < 256 - VISIBLE_PALETTE_ROWS)
937             {
938                 frame->Scroll(256 - VISIBLE_PALETTE_ROWS - frame->GetTopIndex());
939             }
940             break;
941 
942         case VK_PRIOR:
943             next_focus_owner = focus_owner;
944             frame->Scroll(-VISIBLE_PALETTE_ROWS);
945             break;
946 
947         case VK_NEXT:
948             next_focus_owner = focus_owner;
949             frame->Scroll(VISIBLE_PALETTE_ROWS);
950             break;
951 
952         default:
953             return express_table_row::PreTranslateMessage(pMsg);
954         }
955 
956         if (next_focus_owner == focus_owner)
957         {
958             next_focus_owner->NotifyWinEvent(EVENT_OBJECT_NAMECHANGE, OBJID_CLIENT, CHILDID_SELF);
959             CString msg(L"edit ");
960             if (::GetWindowLongPtr(next_focus_owner->GetSafeHwnd(), GWL_STYLE) & ES_READONLY)
961             {
962                 msg.Append(L"read only ");
963             }
964             msg.Append(L"Use arrow keys to navigate.");
965             frame->UpdateStatusMsg(msg);
966         }
967 
968         AssignFocus(next_focus_owner);
969         return TRUE;
970     }
971 
972     return express_table_row::PreTranslateMessage(pMsg);
973 }
974 
975 
BEGIN_MESSAGE_MAP(palette_frame,CWnd)976 BEGIN_MESSAGE_MAP(palette_frame, CWnd)
977     ON_WM_CREATE()
978     ON_WM_SETFOCUS()
979 END_MESSAGE_MAP()
980 
981 ///////////////////////////////////////////////////////////////////////////////
982 palette_frame::palette_frame(theme_info *theme)
983 {
984     mpTheme = theme;
985     mTopIndex = 0;
986 }
987 
988 ///////////////////////////////////////////////////////////////////////////////
~palette_frame()989 palette_frame::~palette_frame()
990 {
991 };
992 
993 ///////////////////////////////////////////////////////////////////////////////
OnCreate(LPCREATESTRUCT lpCreateStruct)994 int palette_frame::OnCreate(LPCREATESTRUCT lpCreateStruct)
995 {
996     if (CWnd::OnCreate(lpCreateStruct) == -1)
997         return -1;
998 
999     // TODO:  Add your specialized creation code here
1000     int index;
1001     CRect client;
1002 
1003     GetClientRect(&client);
1004     int row_height = (client.Height() + VISIBLE_PALETTE_ROWS - 1) / VISIBLE_PALETTE_ROWS;
1005 
1006     GetClientRect(&client);
1007     client.bottom = client.top + row_height;
1008 
1009     for (index = 0; index < VISIBLE_PALETTE_ROWS; index++)
1010     {
1011         mPaletteRows[index].Create(target_class_name, _T("PaletteRow"),
1012             WS_CHILD | WS_VISIBLE, client, this, NULL);
1013         client.OffsetRect(0, row_height);
1014     }
1015 
1016     SetRowData();
1017 
1018     mStatusMsg.Create(L"", WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this);
1019     SetLiveRegion(mStatusMsg.GetSafeHwnd());
1020     return 0;
1021 }
1022 
1023 ///////////////////////////////////////////////////////////////////////////////
OnSetFocus(CWnd * pOldWnd)1024 void palette_frame::OnSetFocus(CWnd* pOldWnd)
1025 {
1026     CWnd::OnSetFocus(pOldWnd);
1027 
1028     //pick first row
1029     palette_row* parent = (palette_row*)GetWindow(GW_CHILD);
1030     CWnd* child;
1031 
1032     // set focus to the first child that has WS_TABSTOP style
1033     if (parent)
1034     {
1035         //pick first child of the row
1036         child = parent->GetWindow(GW_CHILD);
1037 
1038         //loop through child list until we find a child with WS_TABSTOP style,
1039         //and pass focus to this child
1040         while (child)
1041         {
1042             if (child->GetStyle() & WS_TABSTOP)
1043             {
1044                 parent->AssignFocus(child);
1045                 break;
1046             }
1047 
1048             child = child->GetWindow(GW_HWNDNEXT);
1049         }
1050     }
1051     // TODO: Add your message handler code here
1052 }
1053 
1054 ///////////////////////////////////////////////////////////////////////////////
SetRowData()1055 void palette_frame::SetRowData()
1056 {
1057     int index;
1058     BOOL Enabled;
1059     GX_COLOR color;
1060     int slot;
1061 
1062     for (index = 0; index < VISIBLE_PALETTE_ROWS; index++)
1063     {
1064         slot = index + mTopIndex;
1065         if (slot < mpTheme->palette_predefined)
1066         {
1067             Enabled = TRUE;
1068         }
1069         else
1070         {
1071             Enabled = FALSE;
1072         }
1073 
1074         color = mpTheme->palette[slot];
1075         mPaletteRows[index].SetData(index + mTopIndex, color, Enabled);
1076     }
1077 }
1078 
1079 ///////////////////////////////////////////////////////////////////////////////
NotifyColorChanged(int index,GX_COLOR color)1080 void palette_frame::NotifyColorChanged(int index, GX_COLOR color)
1081 {
1082     PaletteLayoutDlg* dlg = (PaletteLayoutDlg*)GetParent();
1083 
1084     dlg->NotifyColorChanged(index, color);
1085 }
1086 
1087 ///////////////////////////////////////////////////////////////////////////////
Scroll(int deltaPos)1088 void palette_frame::Scroll(int deltaPos)
1089 {
1090     PaletteLayoutDlg* dlg = (PaletteLayoutDlg*)GetParent();
1091     dlg->Scroll(deltaPos);
1092 }
1093 
1094 ///////////////////////////////////////////////////////////////////////////////
UpdateStatusMsg(CString msg)1095 void palette_frame::UpdateStatusMsg(CString msg)
1096 {
1097     mStatusMsg.SetWindowText(msg);
1098     mStatusMsg.NotifyWinEvent(
1099         EVENT_OBJECT_LIVEREGIONCHANGED,
1100         OBJID_CLIENT,
1101         CHILDID_SELF);
1102 }
1103