2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
34 #include "PropertyList.h"
36 #include "../comafx/DialogColorPicker.h"
41 static char THIS_FILE[] = __FILE__;
44 /////////////////////////////////////////////////////////////////////////////
47 CPropertyList::CPropertyList() {
49 updateInspectors = false;
52 CPropertyList::~CPropertyList() {
56 BEGIN_MESSAGE_MAP(CPropertyList, CListBox)
57 //{{AFX_MSG_MAP(CPropertyList)
59 ON_CONTROL_REFLECT(LBN_SELCHANGE, OnSelchange)
65 ON_CBN_CLOSEUP(IDC_PROPCMBBOX, OnKillfocusCmbBox)
66 ON_CBN_SELCHANGE(IDC_PROPCMBBOX, OnSelchangeCmbBox)
67 ON_EN_KILLFOCUS(IDC_PROPEDITBOX, OnKillfocusEditBox)
68 ON_EN_CHANGE(IDC_PROPEDITBOX, OnChangeEditBox)
69 ON_BN_CLICKED(IDC_PROPBTNCTRL, OnButton)
72 /////////////////////////////////////////////////////////////////////////////
73 // CPropertyList message handlers
75 BOOL CPropertyList::PreCreateWindow(CREATESTRUCT& cs) {
76 if (!CListBox::PreCreateWindow(cs)) {
80 cs.style &= ~(LBS_OWNERDRAWVARIABLE | LBS_SORT);
81 cs.style |= LBS_OWNERDRAWFIXED;
90 void CPropertyList::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) {
91 if (measureItem && !measureItem->m_curValue.IsEmpty()) {
95 m_nDivider = rect.Width() / 2;
97 rect.left = m_nDivider;
99 dc->DrawText(measureItem->m_curValue, rect, DT_CALCRECT | DT_LEFT | DT_WORDBREAK);
101 lpMeasureItemStruct->itemHeight = (rect.Height() >= 20) ? rect.Height() : 20; //pixels
103 lpMeasureItemStruct->itemHeight = 20; //pixels
108 void CPropertyList::DrawItem(LPDRAWITEMSTRUCT lpDIS) {
110 dc.Attach(lpDIS->hDC);
111 CRect rectFull = lpDIS->rcItem;
112 CRect rect = rectFull;
114 m_nDivider = rect.Width() / 2;
116 rect.left = m_nDivider;
117 CRect rect2 = rectFull;
118 rect2.right = rect.left - 1;
119 UINT nIndex = lpDIS->itemID;
121 if (nIndex != (UINT) -1) {
122 //get the CPropertyItem for the current row
123 CPropertyItem* pItem = (CPropertyItem*) GetItemDataPtr(nIndex);
124 //draw two rectangles, one for each row column
125 if (pItem->m_nItemType == PIT_VAR) {
126 dc.FillSolidRect(rect2,RGB(220,220,220));
128 dc.FillSolidRect(rect2,RGB(192,192,192));
130 dc.DrawEdge(rect2,EDGE_SUNKEN,BF_BOTTOMRIGHT);
131 dc.DrawEdge(rect,EDGE_SUNKEN,BF_BOTTOM);
133 if (lpDIS->itemState == ODS_SELECTED) {
134 dc.DrawFocusRect(rect2);
137 //write the property name in the first rectangle
138 dc.SetBkMode(TRANSPARENT);
139 dc.DrawText(pItem->m_propName,CRect(rect2.left+3,rect2.top+3,
140 rect2.right-3,rect2.bottom+3),
141 DT_LEFT | DT_SINGLELINE);
143 //write the initial property value in the second rectangle
144 dc.DrawText(pItem->m_curValue,CRect(rect.left+3,rect.top+3, rect.right+3,rect.bottom+3), DT_LEFT | (pItem->m_nItemType == PIT_VAR) ? DT_WORDBREAK : DT_SINGLELINE);
149 int CPropertyList::AddItem(CString txt) {
151 int nIndex = AddString(txt);
155 int CPropertyList::AddPropItem(CPropertyItem* pItem) {
156 if (pItem->m_nItemType == PIT_VAR) {
161 int nIndex = AddString(_T(""));
163 SetItemDataPtr(nIndex,pItem);
167 int CPropertyList::OnCreate(LPCREATESTRUCT lpCreateStruct) {
168 if (CListBox::OnCreate(lpCreateStruct) == -1) {
176 m_hCursorSize = AfxGetApp()->LoadStandardCursor(IDC_SIZEWE);
177 m_hCursorArrow = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
179 m_SSerif8Font.CreatePointFont(80,_T("MS Sans Serif"));
184 void CPropertyList::OnSelchange() {
187 static int recurse = 0;
188 //m_curSel = GetCurSel();
191 GetItemRect(m_curSel,rect);
192 rect.left = m_nDivider;
194 CPropertyItem* pItem = (CPropertyItem*) GetItemDataPtr(m_curSel);
196 if (updateInspectors) {
197 g_Inspectors->entityDlg.SetKeyVal(pItem->m_propName, pItem->m_curValue);
201 m_btnCtrl.ShowWindow(SW_HIDE);
204 if (pItem->m_nItemType==PIT_COMBO) {
205 //display the combo box. If the combo box has already been
206 //created then simply move it to the new location, else create it
209 m_cmbBox.MoveWindow(rect);
212 m_cmbBox.Create(CBS_DROPDOWNLIST | WS_VSCROLL | WS_VISIBLE | WS_CHILD | WS_BORDER,rect,this,IDC_PROPCMBBOX);
213 m_cmbBox.SetFont(&m_SSerif8Font);
216 //add the choices for this particular property
217 CString cmbItems = pItem->m_cmbItems;
218 lBoxSelText = pItem->m_curValue;
220 m_cmbBox.ResetContent();
221 m_cmbBox.AddString("");
224 while ((i2=cmbItems.Find('|',i)) != -1) {
225 m_cmbBox.AddString(cmbItems.Mid(i,i2-i));
229 m_cmbBox.ShowWindow(SW_SHOW);
230 //m_cmbBox.SetFocus();
232 //jump to the property's current value in the combo box
233 int j = m_cmbBox.FindStringExact(0,lBoxSelText);
235 m_cmbBox.SetCurSel(j);
237 m_cmbBox.SetCurSel(0);
239 //m_cmbBox.ShowDropDown();
241 else if (pItem->m_nItemType==PIT_EDIT) {
244 m_prevSel = m_curSel;
247 m_editBox.MoveWindow(rect);
249 m_editBox.Create(ES_LEFT | ES_AUTOHSCROLL | WS_VISIBLE | WS_CHILD | WS_BORDER,rect,this,IDC_PROPEDITBOX);
250 m_editBox.SetFont(&m_SSerif8Font);
253 lBoxSelText = pItem->m_curValue;
255 m_editBox.ShowWindow(SW_SHOW);
256 m_editBox.SetFocus();
257 //set the text in the edit box to the property's current value
258 bool b = updateInspectors;
259 updateInspectors = false;
260 m_editBox.SetWindowText(lBoxSelText);
261 updateInspectors = b;
262 } else if (pItem->m_nItemType != PIT_VAR) {
267 void CPropertyList::DisplayButton(CRect region) {
268 //displays a button if the property is a file/color/font chooser
270 m_prevSel = m_curSel;
272 if (region.Width() > 25) {
273 region.left = region.right - 25;
278 m_btnCtrl.MoveWindow(region);
280 m_btnCtrl.Create("...",BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,region,this,IDC_PROPBTNCTRL);
281 m_btnCtrl.SetFont(&m_SSerif8Font);
284 m_btnCtrl.ShowWindow(SW_SHOW);
285 m_btnCtrl.SetFocus();
288 void CPropertyList::ResetContent() {
289 if (m_btnCtrl.GetSafeHwnd()) {
290 m_btnCtrl.ShowWindow(SW_HIDE);
292 int c = this->GetCount();
293 for (int i = 0; i < c; i++) {
294 CPropertyItem *pi = reinterpret_cast<CPropertyItem*>(GetItemDataPtr(i));
299 CListBox::ResetContent();
302 void CPropertyList::OnKillFocus(CWnd* pNewWnd) {
303 //m_btnCtrl.ShowWindow(SW_HIDE);
304 CListBox::OnKillFocus(pNewWnd);
307 void CPropertyList::OnKillfocusCmbBox() {
308 m_cmbBox.ShowWindow(SW_HIDE);
312 void CPropertyList::OnKillfocusEditBox() {
314 m_editBox.ShowWindow(SW_HIDE);
318 void CPropertyList::OnSelchangeCmbBox() {
321 m_cmbBox.GetLBText(m_cmbBox.GetCurSel(),selStr);
322 CPropertyItem* pItem = (CPropertyItem*) GetItemDataPtr(m_curSel);
323 pItem->m_curValue = selStr;
324 if (updateInspectors) {
325 g_Inspectors->entityDlg.UpdateFromListBox();
330 void CPropertyList::OnChangeEditBox() {
332 m_editBox.GetWindowText(newStr);
334 CPropertyItem* pItem = (CPropertyItem*) GetItemDataPtr(m_curSel);
335 pItem->m_curValue = newStr;
338 void CPropertyList::OnButton() {
339 CPropertyItem* pItem = (CPropertyItem*) GetItemDataPtr(m_curSel);
341 //display the appropriate common dialog depending on what type
342 //of chooser is associated with the property
343 if (pItem->m_nItemType == PIT_COLOR) {
345 sscanf(pItem->m_curValue, "%f %f %f", &color.x, &color.y, &color.z);
347 COLORREF cr = (int)(color.x * 255) + (((int)(color.y * 255))<<8) + (((int)(color.z * 255))<<16);
349 CDialogColorPicker dlg(cr);
351 dlg.UpdateParent = UpdateRadiantColor;
353 if (dlg.DoModal() == IDOK) {
354 color.x = (dlg.GetColor() & 255)/255.0;
355 color.y = ((dlg.GetColor() >> 8)&255)/255.0;
356 color.z = ((dlg.GetColor() >> 16)&255)/255.0;
357 pItem->m_curValue = color.ToString(4);
359 if (updateInspectors) {
360 g_Inspectors->entityDlg.UpdateFromListBox();
362 m_btnCtrl.ShowWindow(SW_HIDE);
364 } else if (pItem->m_nItemType == PIT_FILE) {
365 CString SelectedFile;
366 CString Filter("Gif Files (*.gif)|*.gif||");
368 CFileDialog FileDlg(TRUE, NULL, NULL, NULL, Filter);
370 CString currPath = pItem->m_curValue;
371 FileDlg.m_ofn.lpstrTitle = "Select file";
372 if (currPath.GetLength() > 0) {
373 FileDlg.m_ofn.lpstrInitialDir = currPath.Left(currPath.GetLength() - currPath.ReverseFind('\\'));
376 if(IDOK == FileDlg.DoModal()) {
377 SelectedFile = FileDlg.GetPathName();
378 m_btnCtrl.ShowWindow(SW_HIDE);
379 pItem->m_curValue = SelectedFile;
382 } else if (pItem->m_nItemType == PIT_FONT) {
383 CFontDialog FontDlg(NULL,CF_EFFECTS | CF_SCREENFONTS,NULL,this);
384 if(IDOK == FontDlg.DoModal()) {
385 CString faceName = FontDlg.GetFaceName();
386 m_btnCtrl.ShowWindow(SW_HIDE);
387 pItem->m_curValue = faceName;
390 } else if (pItem->m_nItemType == PIT_MODEL) {
391 CPreviewDlg *dlg = CEntityDlg::ShowModelChooser();
392 if (dlg->returnCode == IDOK) {
393 pItem->m_curValue = dlg->mediaName;
394 m_btnCtrl.ShowWindow(SW_HIDE);
395 if (updateInspectors) {
396 g_Inspectors->entityDlg.UpdateFromListBox();
400 } else if (pItem->m_nItemType == PIT_GUI) {
401 CPreviewDlg *dlg = CEntityDlg::ShowGuiChooser();
402 if (dlg->returnCode == IDOK) {
403 pItem->m_curValue = dlg->mediaName;
404 m_btnCtrl.ShowWindow(SW_HIDE);
405 if (updateInspectors) {
406 g_Inspectors->entityDlg.UpdateFromListBox();
410 } else if (pItem->m_nItemType == PIT_MATERIAL) {
411 CPreviewDlg *dlg = CEntityDlg::ShowMaterialChooser();
412 if (dlg->returnCode == IDOK) {
413 pItem->m_curValue = dlg->mediaName;
414 m_btnCtrl.ShowWindow(SW_HIDE);
415 if (updateInspectors) {
416 g_Inspectors->entityDlg.UpdateFromListBox();
423 void CPropertyList::OnLButtonUp(UINT nFlags, CPoint point) {
425 //if columns were being resized then this indicates
426 //that mouse is up so resizing is done. Need to redraw
427 //columns to reflect their new widths.
430 //if mouse was captured then release it
431 if (GetCapture()==this) {
438 InvertLine(&dc,CPoint(point.x,m_nDivTop),CPoint(point.x,m_nDivBtm));
439 //set the divider position to the new value
440 m_nDivider = point.x;
446 int i = ItemFromPoint(point,loc);
448 CListBox::OnLButtonUp(nFlags, point);
452 void CPropertyList::OnLButtonDown(UINT nFlags, CPoint point) {
453 if ((point.x>=m_nDivider-5) && (point.x<=m_nDivider+5)) {
454 //if mouse clicked on divider line, then start resizing
455 ::SetCursor(m_hCursorSize);
457 GetWindowRect(windowRect);
458 windowRect.left += 10; windowRect.right -= 10;
459 //do not let mouse leave the list box boundary
460 ::ClipCursor(windowRect);
463 m_cmbBox.ShowWindow(SW_HIDE);
466 m_editBox.ShowWindow(SW_HIDE);
470 GetClientRect(clientRect);
473 m_nDivTop = clientRect.top;
474 m_nDivBtm = clientRect.bottom;
475 m_nOldDivX = point.x;
478 InvertLine(&dc,CPoint(m_nOldDivX,m_nDivTop),CPoint(m_nOldDivX,m_nDivBtm));
484 CListBox::OnLButtonDown(nFlags, point);
488 void CPropertyList::OnMouseMove(UINT nFlags, CPoint point) {
490 //move divider line to the mouse pos. if columns are
491 //currently being resized
493 //remove old divider line
494 InvertLine(&dc,CPoint(m_nOldDivX,m_nDivTop),CPoint(m_nOldDivX,m_nDivBtm));
495 //draw new divider line
496 InvertLine(&dc,CPoint(point.x,m_nDivTop),CPoint(point.x,m_nDivBtm));
497 m_nOldDivX = point.x;
498 } else if ((point.x >= m_nDivider-5) && (point.x <= m_nDivider+5)) {
499 //set the cursor to a sizing cursor if the cursor is over the row divider
500 ::SetCursor(m_hCursorSize);
502 CListBox::OnMouseMove(nFlags, point);
506 void CPropertyList::InvertLine(CDC* pDC,CPoint ptFrom,CPoint ptTo) {
507 int nOldMode = pDC->SetROP2(R2_NOT);
510 pDC->SetROP2(nOldMode);
513 void CPropertyList::PreSubclassWindow() {
519 m_hCursorSize = AfxGetApp()->LoadStandardCursor(IDC_SIZEWE);
520 m_hCursorArrow = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
522 m_SSerif8Font.CreatePointFont(80,_T("MS Sans Serif"));
526 void CPropertyList::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) {
528 m_cmbBox.ShowWindow(SW_HIDE);
531 m_editBox.ShowWindow(SW_HIDE);
534 m_btnCtrl.ShowWindow(SW_HIDE);
538 CListBox::OnVScroll(nSBCode, nPos, pScrollBar);