root / trunk / win / Libdlg.cpp

Revision 716, 12.8 kB (checked in by leo, 16 months ago)

Renamed array helper classes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// LibDlg.cpp : implementation file
2//
3
4#include "lc_global.h"
5#include "leocad.h"
6#include "LibDlg.h"
7#include "GroupDlg.h"
8#include "Print.h"
9#include "Tools.h"
10#include "texdlg.h"
11#include "ProgDlg.h"
12#include "project.h"
13#include "pieceinf.h"
14#include "globals.h"
15#include "system.h"
16#include "library.h"
17#include "lc_application.h"
18
19#ifdef _DEBUG
20#define new DEBUG_NEW
21#undef THIS_FILE
22static char THIS_FILE[] = __FILE__;
23#endif
24
25// Function to sort the list control.
26static int CALLBACK ListCompare(LPARAM lP1, LPARAM lP2, LPARAM lParamSort)
27{
28    int ret;
29
30    if ((lP1 < 0) || (lP2 < 0))
31        return 0;
32
33    if ((lParamSort & ~0xF0) == 0)
34        ret = _strcmpi(((PieceInfo*)lP1)->m_strDescription, ((PieceInfo*)lP2)->m_strDescription);
35    else
36        ret = _strcmpi(((PieceInfo*)lP1)->m_strName, ((PieceInfo*)lP2)->m_strName);
37
38    return ret;
39}
40
41/////////////////////////////////////////////////////////////////////////////
42// CLibraryDlg dialog
43
44CLibraryDlg::CLibraryDlg(CWnd* pParent /*=NULL*/)
45    : CDialog(CLibraryDlg::IDD, pParent)
46{
47    m_SortColumn = 0;
48
49    //{{AFX_DATA_INIT(CLibraryDlg)
50        // NOTE: the ClassWizard will add member initialization here
51    //}}AFX_DATA_INIT
52}
53
54CLibraryDlg::~CLibraryDlg()
55{
56}
57
58void CLibraryDlg::DoDataExchange(CDataExchange* pDX)
59{
60    CDialog::DoDataExchange(pDX);
61    //{{AFX_DATA_MAP(CLibraryDlg)
62    DDX_Control(pDX, IDC_LIBDLG_TREE, m_Tree);
63    DDX_Control(pDX, IDC_LIBDLG_LIST, m_List);
64    //}}AFX_DATA_MAP
65}
66
67
68BEGIN_MESSAGE_MAP(CLibraryDlg, CDialog)
69    //{{AFX_MSG_MAP(CLibraryDlg)
70    ON_NOTIFY(TVN_SELCHANGED, IDC_LIBDLG_TREE, OnSelChangedTree)
71    ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIBDLG_LIST, OnListColumnClick)
72    //}}AFX_MSG_MAP
73    ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
74    ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
75END_MESSAGE_MAP()
76
77/////////////////////////////////////////////////////////////////////////////
78// CLibraryDlg message handlers
79
80BOOL CLibraryDlg::OnInitDialog()
81{
82    CDialog::OnInitDialog();
83   
84    // Add the ToolBar.
85    if (!m_wndToolBar.Create(this) || !m_wndToolBar.LoadToolBar(IDR_LIBRARY))
86    {
87        TRACE0("Failed to create toolbar\n");
88        return -1;      // fail to create
89    }
90
91    m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY);
92
93    // We need to resize the dialog to make room for control bars.
94    // First, figure out how big the control bars are.
95    CRect rcClientStart;
96    CRect rcClientNow;
97    GetClientRect(rcClientStart);
98    RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0, reposQuery, rcClientNow);
99
100    // Now move all the controls so they are in the same relative
101    // position within the remaining client area as they would be
102    // with no control bars.
103    CPoint ptOffset(rcClientNow.left - rcClientStart.left, rcClientNow.top - rcClientStart.top);
104
105    CRect  rcChild;
106    CWnd* pwndChild = GetWindow(GW_CHILD);
107    while (pwndChild)
108    {
109        pwndChild->GetWindowRect(rcChild);
110        ScreenToClient(rcChild);
111        rcChild.OffsetRect(ptOffset);
112        pwndChild->MoveWindow(rcChild, FALSE);
113        pwndChild = pwndChild->GetNextWindow();
114    }
115
116    // Adjust the dialog window dimensions
117    CRect rcWindow;
118    GetWindowRect(rcWindow);
119    rcWindow.right += rcClientStart.Width() - rcClientNow.Width();
120    rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();
121    MoveWindow(rcWindow, FALSE);
122
123    // And position the control bars
124    RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
125
126    m_TreeImages.Create(IDB_PARTICONS, 16, 0, RGB (0,128,128));
127    m_Tree.SetImageList(&m_TreeImages, TVSIL_NORMAL);
128
129    RECT rect;
130    m_List.GetWindowRect(&rect);
131    m_List.InsertColumn(0, "Name", LVCFMT_LEFT, rect.right - rect.left - GetSystemMetrics(SM_CXVSCROLL) - 4 - 60, 0);
132    m_List.InsertColumn(1, "Number", LVCFMT_LEFT, 60, 1);
133
134    UpdateList();
135    UpdateTree();
136
137    return TRUE;
138}
139
140BOOL CLibraryDlg::OnCommand(WPARAM wParam, LPARAM lParam)
141{
142    switch (LOWORD(wParam))
143    {
144        case ID_LIBDLG_FILE_OPEN:
145        {
146            lcGetPiecesLibrary()->LoadCategories(NULL);
147            UpdateTree();
148            return TRUE;
149        }
150
151        case ID_LIBDLG_FILE_SAVE:
152        {
153            lcGetPiecesLibrary()->DoSaveCategories(false);
154            return TRUE;
155        }
156
157        case ID_LIBDLG_FILE_SAVEAS:
158        {
159            lcGetPiecesLibrary()->DoSaveCategories(true);
160            return TRUE;
161        }
162
163        case ID_LIBDLG_FILE_PRINTCATALOG:
164        {
165            PRINT_PARAMS* param = (PRINT_PARAMS*)malloc(sizeof(PRINT_PARAMS));
166            param->pParent = this;
167            param->pMainFrame = (CFrameWnd*)AfxGetMainWnd();
168            AfxBeginThread(PrintCatalogFunction, param);
169
170            return TRUE;
171        }
172
173        case ID_LIBDLG_FILE_MERGEUPDATE:
174        {
175            LC_FILEOPENDLG_OPTS opts;
176
177            strcpy(opts.path, "");
178            opts.type = LC_FILEOPENDLG_LUP;
179
180            if (SystemDoDialog(LC_DLG_FILE_OPEN, &opts))
181            {
182                lcGetPiecesLibrary()->LoadUpdate((char*)opts.filenames);
183
184                free(opts.filenames);
185
186                UpdateTree();
187            }
188
189            return TRUE;
190        }
191
192        case ID_FILE_IMPORTPIECE:
193        {
194            LC_FILEOPENDLG_OPTS opts;
195
196            strcpy(opts.path, Sys_ProfileLoadString ("Default", "LDraw Pieces Path", ""));
197            opts.type = LC_FILEOPENDLG_DAT;
198
199            if (SystemDoDialog (LC_DLG_FILE_OPEN, &opts))
200            {
201                for (int i = 0; i < opts.numfiles; i++)
202                {
203                    lcGetPiecesLibrary ()->ImportLDrawPiece (opts.filenames[i]);
204                    free (opts.filenames[i]);
205                }
206
207                free (opts.filenames);
208                Sys_ProfileSaveString ("Default", "LDraw Pieces Path", opts.path);
209
210                UpdateList();
211            }
212
213            return TRUE;
214        }
215
216        case ID_LIBDLG_FILE_TEXTURES:
217        {
218            CTexturesDlg dlg;
219            dlg.DoModal();
220        } break;
221
222        case ID_LIBDLG_CATEGORY_RESET:
223        {
224            if (SystemDoMessageBox("Are you sure you want to reset the categories?", LC_MB_YESNO | LC_MB_ICONQUESTION) == LC_YES)
225            {
226                lcGetPiecesLibrary()->ResetCategories();
227
228                UpdateList();
229                UpdateTree();
230            }
231
232            return TRUE;
233        }
234
235        case ID_LIBDLG_CATEGORY_NEW:
236        {
237            LC_CATEGORYDLG_OPTS Opts;
238            Opts.Name = "New Category";
239            Opts.Keywords = "";
240
241            if (SystemDoDialog(LC_DLG_EDITCATEGORY, &Opts))
242            {
243                lcGetPiecesLibrary()->AddCategory(Opts.Name, Opts.Keywords);
244            }
245
246            UpdateTree();
247
248            return TRUE;
249        }
250
251        case ID_LIBDLG_CATEGORY_REMOVE:
252        {
253            HTREEITEM Item = m_Tree.GetSelectedItem();
254
255            if (Item == NULL)
256                break;
257
258            PiecesLibrary* Lib = lcGetPiecesLibrary();
259            CString CategoryName = m_Tree.GetItemText(Item);
260            int Index = Lib->FindCategoryIndex((const char*)CategoryName);
261
262            if (Index == -1)
263                break;
264
265            char Msg[1024];
266            String Name = Lib->GetCategoryName(Index);
267            sprintf(Msg, "Are you sure you want to remove the %s category?", Name);
268
269            if (SystemDoMessageBox(Msg, LC_MB_YESNO | LC_MB_ICONQUESTION) == LC_YES)
270            {
271                Lib->RemoveCategory(Index);
272            }
273
274            UpdateTree();
275
276            return TRUE;
277        }
278
279        case ID_LIBDLG_CATEGORY_EDIT:
280        {
281            HTREEITEM Item = m_Tree.GetSelectedItem();
282
283            if (Item == NULL)
284                break;
285
286            PiecesLibrary* Lib = lcGetPiecesLibrary();
287            CString CategoryName = m_Tree.GetItemText(Item);
288            int Index = Lib->FindCategoryIndex((const char*)CategoryName);
289
290            if (Index == -1)
291                break;
292
293            LC_CATEGORYDLG_OPTS Opts;
294            Opts.Name = Lib->GetCategoryName(Index);
295            Opts.Keywords = Lib->GetCategoryKeywords(Index);
296
297            if (SystemDoDialog(LC_DLG_EDITCATEGORY, &Opts))
298            {
299                String OldName = Lib->GetCategoryName(Index);
300                Lib->SetCategory(Index, Opts.Name, Opts.Keywords);
301            }
302
303            UpdateTree();
304
305            return TRUE;
306        }
307
308        case ID_LIBDLG_PIECE_NEW:
309        {
310            return TRUE;
311        }
312
313        case ID_LIBDLG_PIECE_EDIT:
314        {
315            return TRUE;
316        }
317
318        case ID_LIBDLG_PIECE_DELETE:
319        {
320            lcPtrArray<PieceInfo> Pieces;
321
322            for (int i = 0; i < m_List.GetItemCount(); i++)
323            {
324                if (m_List.GetItemState(i, LVIS_SELECTED))
325                    Pieces.Add((PieceInfo*)m_List.GetItemData(i));
326            }
327
328            if (Pieces.GetSize() == 0)
329                return TRUE;
330
331            if (SystemDoMessageBox ("Are you sure you want to permanently delete the selected pieces?", LC_MB_YESNO|LC_MB_ICONQUESTION) != LC_YES)
332                return TRUE;
333
334            lcGetPiecesLibrary()->DeletePieces(Pieces);
335
336            UpdateList();
337
338            return TRUE;
339        }
340    }
341
342    return CDialog::OnCommand(wParam, lParam);
343}
344
345void CLibraryDlg::UpdateList()
346{
347    m_List.DeleteAllItems();
348    m_List.SetRedraw(FALSE);
349
350    PiecesLibrary *Lib = lcGetPiecesLibrary();
351
352    HTREEITEM CategoryItem = m_Tree.GetSelectedItem();
353    CString CategoryName = m_Tree.GetItemText(CategoryItem);
354    int CategoryIndex = Lib->FindCategoryIndex((const char*)CategoryName);
355
356    if (CategoryIndex != -1)
357    {
358        lcPtrArray<PieceInfo> SinglePieces, GroupedPieces;
359
360        Lib->GetCategoryEntries(CategoryIndex, false, SinglePieces, GroupedPieces);
361
362        for (int i = 0; i < SinglePieces.GetSize(); i++)
363        {
364            PieceInfo* Info = SinglePieces[i];
365
366            LVITEM lvi;
367            lvi.mask = LVIF_TEXT | LVIF_PARAM;
368            lvi.iItem = 0;
369            lvi.iSubItem = 0;
370            lvi.lParam = (LPARAM)Info;
371            lvi.pszText = Info->m_strDescription;
372            int idx = m_List.InsertItem(&lvi);
373
374            m_List.SetItemText(idx, 1, Info->m_strName);
375        }
376    }
377    else
378    {
379        if (CategoryName == "Unassigned")
380        {
381            // Test each piece against all categories.
382            for (int i = 0; i < Lib->GetPieceCount(); i++)
383            {
384                PieceInfo* Info = Lib->GetPieceInfo(i);
385                int j;
386
387                for (j = 0; j < Lib->GetNumCategories(); j++)
388                {
389                    if (Lib->PieceInCategory(Info, Lib->GetCategoryKeywords(j)))
390                        break;
391                }
392
393                if (j == Lib->GetNumCategories())
394                {
395                    LVITEM lvi;
396                    lvi.mask = LVIF_TEXT | LVIF_PARAM;
397                    lvi.iItem = 0;
398                    lvi.iSubItem = 0;
399                    lvi.lParam = (LPARAM)Info;
400                    lvi.pszText = Info->m_strDescription;
401                    int idx = m_List.InsertItem(&lvi);
402
403                    m_List.SetItemText(idx, 1, Info->m_strName);
404                }
405            }
406        }
407        else if (CategoryName == "Pieces")
408        {
409            for (int i = 0; i < Lib->GetPieceCount(); i++)
410            {
411                PieceInfo* Info = Lib->GetPieceInfo(i);
412
413                LVITEM lvi;
414                lvi.mask = LVIF_TEXT | LVIF_PARAM;
415                lvi.iItem = 0;
416                lvi.iSubItem = 0;
417                lvi.lParam = (LPARAM)Info;
418                lvi.pszText = Info->m_strDescription;
419                int idx = m_List.InsertItem(&lvi);
420
421                m_List.SetItemText(idx, 1, Info->m_strName);
422            }
423        }
424    }
425
426    m_List.SortItems((PFNLVCOMPARE)ListCompare, m_SortColumn);
427    m_List.SetRedraw(TRUE);
428}
429
430void CLibraryDlg::UpdateTree()
431{
432    m_Tree.SetRedraw(FALSE);
433    m_Tree.DeleteAllItems();
434
435    HTREEITEM Root = m_Tree.InsertItem(TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT, "Pieces", 0, 1, 0, 0, 0, TVI_ROOT, TVI_SORT);
436
437    PiecesLibrary *Lib = lcGetPiecesLibrary();
438    for (int i = 0; i < Lib->GetNumCategories(); i++)
439        m_Tree.InsertItem(TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM|TVIF_TEXT, Lib->GetCategoryName(i), 0, 1, 0, 0, 0, Root, TVI_SORT);
440
441    m_Tree.InsertItem(TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM|TVIF_TEXT, "Unassigned", 0, 1, 0, 0, 0, Root, TVI_LAST);
442
443    m_Tree.Expand(Root, TVE_EXPAND);
444    m_Tree.SetRedraw(TRUE);
445    m_Tree.Invalidate();
446}
447
448void CLibraryDlg::OnSelChangedTree(NMHDR* pNMHDR, LRESULT* pResult)
449{
450    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
451    UpdateList();
452    *pResult = 0;
453}
454
455void CLibraryDlg::OnCancel()
456{
457    // Check if it's ok to close the dialog
458    if (!lcGetPiecesLibrary()->SaveCategories())
459        return;
460
461    CDialog::OnCancel();
462}
463
464void CLibraryDlg::OnOK()
465{
466    // Check if it's ok to close the dialog
467    if (!lcGetPiecesLibrary()->SaveCategories())
468        return;
469
470    CDialog::OnOK();
471}
472
473BOOL CLibraryDlg::ContinueModal()
474{
475    HTREEITEM h = m_Tree.GetSelectedItem();
476    BOOL bValid = (h != m_Tree.GetRootItem()) && (h != NULL);
477
478    EnableControl(ID_LIBDLG_GROUP_RENAME, bValid);
479    EnableControl(ID_LIBDLG_GROUP_DELETE, bValid);
480
481    return CDialog::ContinueModal();
482}
483
484void CLibraryDlg::EnableControl(UINT nID, BOOL bEnable)
485{
486    GetMenu()->GetSubMenu(1)->EnableMenuItem(nID, MF_BYCOMMAND | (bEnable ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
487    int state = m_wndToolBar.GetToolBarCtrl().GetState(nID) & ~TBSTATE_ENABLED;
488    if (bEnable)
489        state |= TBSTATE_ENABLED;
490    m_wndToolBar.GetToolBarCtrl().SetState(nID, state);
491}
492
493BOOL CLibraryDlg::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult)
494{
495    ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
496
497    // allow top level routing frame to handle the message
498    if (GetRoutingFrame() != NULL)
499        return FALSE;
500   
501    // need to handle both ANSI and UNICODE versions of the message
502    TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
503    TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
504    CString cstTipText;
505    UINT nID = pNMHDR->idFrom;
506
507    if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
508        pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
509    {
510        // idFrom is actually the HWND of the tool
511        nID = ((UINT)(WORD)::GetDlgCtrlID((HWND)nID));
512    }
513   
514    if (nID != 0) // will be zero on a separator
515    {
516        cstTipText.LoadString(nID);
517    }
518   
519    // Non-UNICODE Strings only are shown in the tooltip window...
520    if (pNMHDR->code == TTN_NEEDTEXTA)
521        lstrcpyn(pTTTA->szText, cstTipText, (sizeof(pTTTA->szText)/sizeof(pTTTA->szText[0])));
522    else
523        _mbstowcsz(pTTTW->szText, cstTipText, (sizeof(pTTTW->szText)/sizeof(pTTTW->szText[0])));
524   
525    *pResult = 0;
526   
527    // bring the tooltip window above other popup windows
528    ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
529        SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);
530   
531    return TRUE;    // message was handled
532}
533
534void CLibraryDlg::OnListColumnClick(NMHDR* pNMHDR, LRESULT* pResult)
535{
536    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
537
538    // Save the column index.
539    m_SortColumn = pNMListView->iSubItem;
540
541    m_List.SortItems((PFNLVCOMPARE)ListCompare, m_SortColumn);
542
543    *pResult = 0;
544}
Note: See TracBrowser for help on using the browser.