1 #include "studiox_includes.h"
2 #include "express_table_row.h"
3 #include "string_scroll_wheel_edit_dlg.h"
4 
5 extern CFont NormalFont;
6 
7 enum string_scroll_wheel_edit_dlg_test_commands{
8     TEST_SET_STRING = 1,
9     TEST_SAVE,
10     TEST_CANCEL
11 };
12 
13 enum CONTROL_IDS{
14     ID_STRING_INDEX = 4096,
15     ID_STRING_VAL,
16     ID_STRING_ID
17 };
18 
19 extern CString target_class_name;
20 // string_scroll_wheel_edit_dlg dialog
21 
IMPLEMENT_DYNAMIC(string_scroll_wheel_edit_dlg,express_dialog)22 IMPLEMENT_DYNAMIC(string_scroll_wheel_edit_dlg, express_dialog)
23 
24 BEGIN_MESSAGE_MAP(string_scroll_wheel_edit_dlg, express_dialog)
25     ON_MESSAGE(STUDIO_TEST, OnTestMessage)
26 END_MESSAGE_MAP()
27 
28 ///////////////////////////////////////////////////////////////////////////////
29 string_scroll_wheel_edit_dlg::string_scroll_wheel_edit_dlg(int display_index, CArray<GX_RESOURCE_ID> *value_list, CWnd* pParent /*=NULL*/)
30     : express_dialog(string_scroll_wheel_edit_dlg::IDD, pParent)
31 {
32     IconId = IDB_PROPS_VIEW;
33     SetTitleText("String Scroll Wheel Edit");
34 
35     mpStringIdList = value_list;
36     mOldStringIdList.Copy(*value_list);
37     mDisplayIndex = display_index;
38 
39     studiox_project *project = GetOpenProject();
40 
41     if (project)
42     {
43         mpProject = project;
44 
45         if (project->mDisplays[mDisplayIndex].stable)
46         {
47             mpTable = new string_table(*project->mDisplays[mDisplayIndex].stable);
48         }
49         else
50         {
51             mpTable = new string_table;
52         }
53     }
54     else
55     {
56         exit(1);
57     }
58 }
59 
60 ///////////////////////////////////////////////////////////////////////////////
~string_scroll_wheel_edit_dlg()61 string_scroll_wheel_edit_dlg::~string_scroll_wheel_edit_dlg()
62 {
63     if (mpTable)
64     {
65         delete mpTable;
66     }
67 
68     if (mpValueListFrame)
69     {
70         delete mpValueListFrame;
71     }
72 }
73 
74 ///////////////////////////////////////////////////////////////////////////////
DoDataExchange(CDataExchange * pDX)75 void string_scroll_wheel_edit_dlg::DoDataExchange(CDataExchange* pDX)
76 {
77     express_dialog::DoDataExchange(pDX);
78 
79     if (pDX->m_bSaveAndValidate)
80     {
81         if (mpProject->mDisplays[mDisplayIndex].stable)
82         {
83             delete mpProject->mDisplays[mDisplayIndex].stable;
84             mpTable->Sort();
85             mpProject->mDisplays[mDisplayIndex].stable = mpTable;
86             mpTable = NULL;
87 
88             if (GetResourceView())
89             {
90                 GetResourceView()->RebuildStringItems();
91             }
92         }
93     }
94     else
95     {
96         mpStringIdList->Copy(mOldStringIdList);
97     }
98 }
99 
OnInitDialog()100 BOOL string_scroll_wheel_edit_dlg::OnInitDialog()
101 {
102     express_dialog::OnInitDialog();
103 
104     CRect frame_size;
105     CRect size;
106 
107     GetDlgItem(IDC_INDEX_LABEL)->GetWindowRect(&size);
108     ScreenToClient(&size);
109 
110     GetClientRect(&frame_size);
111 
112     frame_size.left += 5;
113     frame_size.top = size.bottom + 5;
114     frame_size.right -= 5;
115     frame_size.bottom -= m_status_bar_height + 10;
116 
117     // Create value list frame
118     mpValueListFrame = new value_list_frame(mpStringIdList, mpTable);
119     mpValueListFrame->Create(target_class_name, _T("ValueListFrame"),
120         WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER | WS_TABSTOP,
121         frame_size, this, 0);
122 
123     AddCancelButton();
124     AddSaveButton();
125 
126     return TRUE;
127 }
128 
TestSetRowData(int row_id,CString string)129 void string_scroll_wheel_edit_dlg::TestSetRowData(int row_id, CString string)
130 {
131     CWnd* child = mpValueListFrame->GetWindow(GW_CHILD);
132     value_list_row* row;
133 
134 
135     while (child)
136     {
137         row = (value_list_row*)child;
138 
139         if (row->GetRowId() == row_id)
140         {
141             CRect list_client;
142             CRect rect;
143 
144             mpValueListFrame->GetClientRect(&list_client);
145             mpValueListFrame->ClientToScreen(&list_client);
146 
147             row->GetWindowRect(&rect);
148 
149             if (rect.top < list_client.top)
150             {
151                 mpValueListFrame->Scroll(rect.top - list_client.top);
152             }
153             else if (rect.bottom > list_client.bottom)
154             {
155                 mpValueListFrame->Scroll(rect.bottom - list_client.bottom);
156             }
157 
158             row->SetData(_T(""), string);
159             row->SendMessage(WM_COMMAND, MAKEWPARAM(ID_STRING_VAL, EN_KILLFOCUS),
160                 (LPARAM)(row->GetTextEdit()->m_hWnd));
161         }
162         child = child->GetWindow(GW_HWNDNEXT);
163     }
164 }
165 
166 //////////////////////////////////////////////////////////////////////////////
OnTestMessage(WPARAM wParam,LPARAM lParam)167 LRESULT string_scroll_wheel_edit_dlg::OnTestMessage(WPARAM wParam, LPARAM lParam)
168 {
169     CStringArray param;
170     INT id;
171     CString string;
172 
173     switch (wParam)
174     {
175     case TEST_SET_STRING:
176         SplitString(GetTestingParam(0), ',', &param);
177         id = _tstoi(param.GetAt(0));
178         string = param.GetAt(1);
179 
180         TestSetRowData(id, string);
181         break;
182 
183     case TEST_SAVE:
184         OnOK();
185         break;
186 
187     case TEST_CANCEL:
188         OnCancel();
189         break;
190     }
191 
192     return 0;
193 }
194 
BEGIN_MESSAGE_MAP(value_list_row,express_table_row)195 BEGIN_MESSAGE_MAP(value_list_row, express_table_row)
196     ON_WM_CREATE()
197     ON_EN_KILLFOCUS(ID_STRING_VAL, OnChangeStringText)
198     ON_CBN_SELCHANGE(ID_STRING_ID, OnChangeStringId)
199     ON_WM_ERASEBKGND()
200 END_MESSAGE_MAP()
201 
202 ///////////////////////////////////////////////////////////////////////////////
203 value_list_row::value_list_row(int row_id)
204 {
205     mRowId = row_id;
206 }
207 
208 ///////////////////////////////////////////////////////////////////////////////
OnCreate(LPCREATESTRUCT lpCreateStruct)209 int value_list_row::OnCreate(LPCREATESTRUCT lpCreateStruct)
210 {
211     if (express_table_row::OnCreate(lpCreateStruct) == -1)
212         return -1;
213 
214     CRect client;
215     CRect size;
216 
217     // TODO:  Add your specialized creation code here
218     GetClientRect(&client);
219 
220     CFont* font = &NormalFont;
221 
222     size = client;
223     size.top += 5;
224     size.bottom -= 5;
225     size.left += 3;
226     size.right = client.Width() / 3 - 35;
227     CString text;
228     text.Format(_T("%d"), mRowId);
229     mIndexPrompt.Create(text, WS_CHILD | SS_CENTER | WS_VISIBLE, size, this, ID_STRING_INDEX);
230     mIndexPrompt.SetFont(font);
231 
232     size.left = size.right + 15;
233     size.right = client.right - 5;
234 
235     int width = size.right - size.left + 1;
236     size.right = size.left + width / 2 - 5;
237     mStringIdCombo.Create(WS_CHILD | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_SORT | WS_VISIBLE | WS_VSCROLL, size, this, ID_STRING_ID);
238     mStringIdCombo.SetFont(font);
239     SetControlAccessibleName(mStringIdCombo.GetSafeHwnd(), _T("Index ") + text + _T(" String ID"));
240 
241     size.left = size.right + 5;
242     size.right = client.right - 5;
243 
244     mStringTextEdit.Create(WS_CHILD | SS_RIGHT | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, size, this, ID_STRING_VAL);
245     mStringTextEdit.SetFont(font);
246     SetControlAccessibleName(mStringTextEdit.GetSafeHwnd(), _T("Index ") + text + _T(" String Value"));
247 
248     value_list_frame *frame = (value_list_frame*)GetParent();
249     if (frame)
250     {
251         string_table *table = frame->GetStringTable();
252         if (table)
253         {
254             int string_id = 1;
255             int box_index;
256 
257             while (string_id < table->CountStrings())
258             {
259                 box_index = mStringIdCombo.AddString(table->GetResourceIdName(string_id));
260                 mStringIdCombo.SetItemData(box_index, string_id);
261                 string_id++;
262             }
263 
264             mStringIdCombo.InsertString(0, _T("None"));
265             mStringIdCombo.SetItemData(0, 0);
266             mStringIdCombo.SetCurSel(0);
267         }
268     }
269 
270     return 0;
271 }
272 
273 ///////////////////////////////////////////////////////////////////////////////
OnEraseBkgnd(CDC * pDC)274 BOOL value_list_row::OnEraseBkgnd(CDC* pDC)
275 {
276     CBrush newBrush(RGB(210, 210, 210));
277     CBrush *pOldBrush;
278 
279     pOldBrush = pDC->SelectObject(&newBrush);
280 
281     CRect rect;
282     pDC->GetClipBox(&rect);     // Erase the area needed
283 
284     pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),
285         PATCOPY);
286     pDC->SelectObject(pOldBrush);
287     return TRUE;
288 }
289 
290 ///////////////////////////////////////////////////////////////////////////////
PreTranslateKeyDown(WPARAM keyvalue)291 BOOL value_list_row::PreTranslateKeyDown(WPARAM keyvalue)
292 {
293     CWnd* focus_owner = GetFocus();
294     CWnd* next_focus_owner = NULL;
295     value_list_frame* list = (value_list_frame*)GetParent();
296     CRect list_client;
297 
298     list->GetClientRect(&list_client);
299     list->ClientToScreen(&list_client);
300 
301     switch (keyvalue)
302     {
303     case VK_LEFT:
304     case VK_RIGHT:
305     case VK_UP:
306     case VK_DOWN:
307     case VK_HOME:
308     case VK_END:
309         next_focus_owner = GetNextTabStopChild(focus_owner, keyvalue);
310         break;
311 
312     case VK_PRIOR:
313         if (list->Scroll(-list_client.Height()))
314         {
315             next_focus_owner = GetNextTabStopChild(focus_owner, keyvalue, list_client.Height() / list->GetRowHeight());
316         }
317         break;
318 
319     case VK_NEXT:
320         if (list->Scroll(list_client.Height()))
321         {
322             next_focus_owner = GetNextTabStopChild(focus_owner, keyvalue, list_client.Height() / list->GetRowHeight());
323         }
324         break;
325 
326     default:
327         return FALSE;
328     }
329 
330     if (next_focus_owner)
331     {
332         CRect rect;
333 
334         next_focus_owner->GetWindowRect(&rect);
335 
336         if (rect.top < list_client.top)
337         {
338             list->Scroll(rect.top - list_client.top);
339         }
340         else if (rect.bottom > list_client.bottom)
341         {
342             list->Scroll(rect.bottom - list_client.bottom);
343         }
344 
345         AssignFocus(next_focus_owner);
346     }
347 
348     return TRUE;
349 }
350 
351 ///////////////////////////////////////////////////////////////////////////////
PreTranslateMessage(MSG * pMsg)352 BOOL value_list_row::PreTranslateMessage(MSG* pMsg)
353 {
354     // TODO: Add your specialized code here and/or call the base class
355     if (pMsg->message == WM_KEYDOWN)
356     {
357         if (pMsg->wParam == VK_TAB)
358         {
359             //handle tab key
360             value_list_frame* frame = (value_list_frame*)GetParent();
361             string_scroll_wheel_edit_dlg* dlg = (string_scroll_wheel_edit_dlg*)frame->GetParent();
362             CWnd* child = dlg->GetNextDlgTabItem(frame, FALSE);
363             if (child)
364             {
365                 child->SetFocus();
366                 return TRUE;
367             }
368         }
369 
370         CWnd* child = GetFocus();
371         CComboBox* box = NULL;
372         TCHAR  class_name[MAX_PATH];
373         GetClassName(child->GetSafeHwnd(), class_name, MAX_PATH - 1);
374         if (class_name[0] == 'C')
375         {
376             //"ComboBox"
377             box = (CComboBox*)child;
378         }
379 
380         if (!box || !box->GetDroppedState())
381         {
382             if (PreTranslateKeyDown(pMsg->wParam))
383             {
384                 return TRUE;
385             }
386         }
387     }
388 
389     return express_table_row::PreTranslateMessage(pMsg);
390 }
391 
392 ///////////////////////////////////////////////////////////////////////////////
OnChangeStringId()393 void value_list_row::OnChangeStringId()
394 {
395     value_list_frame *frame = (value_list_frame*)GetParent();
396     string_table *table = frame->GetStringTable();
397 
398     int res_id = mStringIdCombo.GetItemData(mStringIdCombo.GetCurSel());
399     CString id_name = table->GetResourceIdName(res_id);
400 
401     if (mStringId != id_name)
402     {
403         mStringId = id_name;
404 
405         SetUtf8Text(&mStringTextEdit, table->GetString(id_name));
406     }
407 
408     frame->NotifyStringIdChanged(mRowId, res_id);
409 }
410 
411 ///////////////////////////////////////////////////////////////////////////////
OnChangeStringText()412 void value_list_row::OnChangeStringText()
413 {
414     value_list_frame *frame = (value_list_frame*)GetParent();
415     string_table *table = frame->GetStringTable();
416     CString string;
417 
418     mStringTextEdit.GetWindowText(string);
419 
420     int   res_id = mStringIdCombo.GetItemData(mStringIdCombo.GetCurSel());
421     CString id_name;
422 
423     if (res_id)
424     {
425         id_name = table->GetResourceIdName(res_id);
426 
427         if (table->GetString(id_name) == string)
428         {
429             // no change, just return
430             return;
431         }
432     }
433 
434     if (string.IsEmpty())
435     {
436         id_name = "";
437         res_id = 0;
438         mStringIdCombo.SetCurSel(0);
439     }
440     else
441     {
442         int string_index = table->CheckAddString(string);
443         id_name = table->GetStringId(string_index);
444         res_id = table->GetResourceId(id_name);
445 
446         if (mStringIdCombo.GetCount() == res_id)
447         {
448             frame->NotifyStringIdAdded(id_name, res_id);
449             mStringIdCombo.SelectString(0, id_name);
450         }
451     }
452     frame->NotifyStringIdChanged(mRowId, res_id);
453 }
454 
455 ///////////////////////////////////////////////////////////////////////////////
SetData(CString id,CString text)456 void value_list_row::SetData(CString id, CString text)
457 {
458     mStringId = id;
459     mStringText = text;
460 
461     if (id.IsEmpty())
462     {
463         mStringIdCombo.SetCurSel(0);
464     }
465     else
466     {
467         mStringIdCombo.SelectString(0, id);
468     }
469     SetDlgItemText(ID_STRING_VAL, text);
470 
471     Invalidate();
472 }
473 
474 ///////////////////////////////////////////////////////////////////////////////
InsertStringId(CString id_name,GX_RESOURCE_ID res_id)475 void value_list_row::InsertStringId(CString id_name, GX_RESOURCE_ID res_id)
476 {
477     int index;
478     index = mStringIdCombo.AddString(id_name);
479     mStringIdCombo.SetItemData(index, res_id);
480 }
481 
482 
BEGIN_MESSAGE_MAP(value_list_frame,CWnd)483 BEGIN_MESSAGE_MAP(value_list_frame, CWnd)
484 ON_WM_CREATE()
485 ON_WM_VSCROLL()
486 ON_WM_MOUSEWHEEL()
487 ON_WM_DESTROY()
488 ON_WM_SETFOCUS()
489 END_MESSAGE_MAP()
490 
491 ///////////////////////////////////////////////////////////////////////////////
492 value_list_frame::value_list_frame(CArray<GX_RESOURCE_ID>* string_id_list, string_table *stable)
493 {
494     mpStringIdList = string_id_list;
495     mpTable = stable;
496     mRowHeight = 0;
497 
498     m_scroll_helper = new CScrollHelper;
499     m_scroll_helper->AttachWnd(this);
500 }
501 
502 ///////////////////////////////////////////////////////////////////////////////
~value_list_frame()503 value_list_frame::~value_list_frame()
504 {
505 
506     if (m_scroll_helper)
507     {
508         delete m_scroll_helper;
509     }
510 }
511 
OnDestroy()512 void value_list_frame::OnDestroy()
513 {
514     CWnd::OnDestroy();
515 
516     // TODO: Add your message handler code here
517     CWnd* child = GetWindow(GW_CHILD);
518 
519     while (child)
520     {
521         child->DestroyWindow();
522         delete child;
523         child = GetWindow(GW_CHILD);
524     }
525 }
526 
527 
528 ///////////////////////////////////////////////////////////////////////////////
OnCreate(LPCREATESTRUCT lpCreateStruct)529 int value_list_frame::OnCreate(LPCREATESTRUCT lpCreateStruct)
530 {
531     if (CWnd::OnCreate(lpCreateStruct) == -1)
532         return -1;
533 
534     // TODO:  Add your specialized creation code here
535     CRect client;
536 
537     GetClientRect(&client);
538     mRowHeight = (client.Height() + VISIBLE_VALUE_ROWS - 1) / VISIBLE_VALUE_ROWS;
539 
540     client.bottom = client.top + mRowHeight;
541 
542     value_list_row *row;
543     int row_count = mpStringIdList->GetCount();
544     int res_id;
545     CString id_name;
546     CString text;
547 
548     //add row window
549     for (int index = 0; index < row_count; index++)
550     {
551         row = new value_list_row(index);
552         row->Create(target_class_name, _T("ValueListRow"), WS_CHILD | WS_VISIBLE, client, this, 0, NULL);
553 
554         res_id = mpStringIdList->GetAt(index);
555         id_name = mpTable->GetResourceIdName(res_id);
556         text = mpTable->GetString(id_name);
557 
558         row->SetData(id_name, text);
559 
560         client.OffsetRect(0, mRowHeight);
561     }
562 
563     m_scroll_helper->SetDisplaySize(0, row_count * mRowHeight);
564 
565     return 0;
566 }
567 
568 ///////////////////////////////////////////////////////////////////////////////
OnVScroll(UINT nSBCode,UINT nPos,CScrollBar * bar)569 void value_list_frame::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* bar)
570 {
571     // Compute the desired change or delta in scroll position.
572     m_scroll_helper->OnVScroll(nSBCode, nPos, bar);
573 }
574 
575 ///////////////////////////////////////////////////////////////////////////////
OnMouseWheel(UINT nFlags,short zDelta,CPoint pt)576 BOOL value_list_frame::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
577 {
578     // TODO: Add your message handler code here and/or call default
579     return m_scroll_helper->OnMouseWheel(nFlags, zDelta, pt);
580 }
581 
582 ///////////////////////////////////////////////////////////////////////////////
OnSetFocus(CWnd * pOldWnd)583 void value_list_frame::OnSetFocus(CWnd* pOldWnd)
584 {
585     CWnd::OnSetFocus(pOldWnd);
586 
587     // TODO: Add your message handler code here
588     //pick first row
589     CWnd* child = GetWindow(GW_CHILD);
590     CRect list_client;
591     CRect rect;
592 
593     GetClientRect(&list_client);
594     ClientToScreen(&list_client);
595 
596     // set focus to the first visible child
597     while (child)
598     {
599         child->GetWindowRect(&rect);
600 
601         if (rect.top < list_client.top)
602         {
603             child = child->GetWindow(GW_HWNDNEXT);
604         }
605         else
606         {
607             //pick first child of the row
608             child = child->GetWindow(GW_CHILD);
609 
610             while (child)
611             {
612                 if (child->GetStyle() & WS_TABSTOP)
613                 {
614                     child->SetFocus();
615                     break;
616                 }
617 
618                 child = child->GetWindow(GW_HWNDNEXT);
619             }
620 
621             break;
622         }
623     }
624 }
625 
626 ///////////////////////////////////////////////////////////////////////////////
NotifyStringIdAdded(CString id_name,GX_RESOURCE_ID res_id)627 void value_list_frame::NotifyStringIdAdded(CString id_name, GX_RESOURCE_ID res_id)
628 {
629     CWnd* child = GetWindow(GW_CHILD);
630 
631     while (child)
632     {
633         ((value_list_row*)child)->InsertStringId(id_name, res_id);
634         child = child->GetWindow(GW_HWNDNEXT);
635     }
636 }
637 
638 ///////////////////////////////////////////////////////////////////////////////
NotifyStringIdChanged(int index,GX_RESOURCE_ID id)639 void value_list_frame::NotifyStringIdChanged(int index, GX_RESOURCE_ID id)
640 {
641     if (index < mpStringIdList->GetCount())
642     {
643         mpStringIdList->SetAt(index, id);
644     }
645 }
646 
647 ///////////////////////////////////////////////////////////////////////////////
Scroll(int delta)648 BOOL value_list_frame::Scroll(int delta)
649 {
650     CSize pos = m_scroll_helper->GetScrollPos();
651     int new_cy;
652 
653     new_cy = pos.cy + delta;
654 
655     if (delta > 0)
656     {
657         CSize display_size = m_scroll_helper->GetDisplaySize();
658         CSize page_size = m_scroll_helper->GetPageSize();
659 
660         int maxScrollPos = display_size.cy - page_size.cy;
661 
662         if (new_cy > maxScrollPos)
663         {
664             new_cy = maxScrollPos;
665         }
666     }
667     else
668     {
669         if (new_cy < 0)
670         {
671             new_cy = 0;
672         }
673     }
674 
675     if (new_cy != pos.cy)
676     {
677         m_scroll_helper->SetScrollPos(SB_VERT, new_cy, TRUE);
678         return TRUE;
679     }
680 
681     return FALSE;
682 }
683