- changed name of package library to package.dll
[reactos.git] / rosapps / packmgr / gui / main.c
1 ////////////////////////////////////////////////////////
2 //
3 // main.cpp
4 //
5 // Implementation of the Package Manager GUI
6 //
7 //
8 // Maarten Bosma, 09.01.2004
9 // maarten.paul@bosma.de
10 //
11 ////////////////////////////////////////////////////////////////////
12
13 #include "main.h"
14
15 // This is the struct where the toolbar is defined
16 const TBBUTTON Buttons [] =
17 {
18 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
19
20 {0, 1, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // No Action
21 {1, 2, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Install
22 {2, 3, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Install from source
23 {3, 4, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Update
24 {4, 5, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Unistall
25
26 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
27 {5, 6, TBSTATE_ENABLED, TBSTYLE_BUTTON}, // DoIt (tm)
28 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
29
30 {6, 7, TBSTATE_ENABLED, TBSTYLE_BUTTON}, // Help
31 {7, 8, TBSTATE_ENABLED, TBSTYLE_BUTTON}, // Options
32
33 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
34 };
35
36
37 // Application's Entry Point
38 int WINAPI WinMain (HINSTANCE hinst, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
39 {
40 HWND hwnd;
41 MSG msg;
42 WNDCLASSEX wc = {0};
43 WCHAR errbuf[2000];
44
45 // Window creation
46 wc.cbSize = sizeof(WNDCLASSEX);
47 wc.lpszClassName = L"pgkmgr";
48 wc.style = CS_HREDRAW | CS_VREDRAW;
49 wc.lpfnWndProc = (WNDPROC)WndProc;
50 wc.hInstance = hinst;
51 wc.hIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_MAIN));
52 wc.hbrBackground = (HBRUSH)(COLOR_SCROLLBAR);
53
54 RegisterClassEx(&wc);
55
56 hwnd = CreateWindow(L"pgkmgr",
57 L"ReactOS - Package Manager v0.3",
58 WS_OVERLAPPEDWINDOW,
59 CW_USEDEFAULT,
60 CW_USEDEFAULT,
61 500, 600,
62 NULL, NULL,
63 hinst,
64 NULL);
65
66
67 // Toolbar creation
68 InitCommonControls();
69
70 hTBar = CreateToolbarEx(hwnd, WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT, 0, 8, hinst, IDB_TOOLBAR,
71 Buttons, sizeof(Buttons)/sizeof(TBBUTTON), TBSIZE, TBSIZE, TBSIZE, TBSIZE, sizeof(TBBUTTON));
72
73 // Show the windows
74 ShowWindow(hwnd, SW_SHOW);
75 UpdateWindow(hwnd);
76
77 // Load the tree
78 int error = PML_LoadTree(&tree, "tree.xml", AddItem);
79
80 if(error)
81 {
82 MessageBox(0,PML_TransError(error, (WCHAR*)errbuf, sizeof(errbuf)/sizeof(WCHAR)),0,0);
83 return 0;
84 }
85
86 // Read the help
87 Help();
88
89 // Start getting messages
90 while(GetMessage(&msg,NULL,0,0))
91 {
92 if(!TranslateAccelerator(hwnd, hHotKeys, &msg))
93 {
94 TranslateMessage(&msg);
95 DispatchMessage(&msg);
96 }
97 }
98
99 // Close our handle
100 PML_CloseTree (tree);
101
102 return 0;
103 }
104
105 // Add a item to our tree
106 int AddItem (int id, const char* name, int parent, int icon)
107 {
108 TV_INSERTSTRUCT tvins;
109
110 tvins.item.lParam = (UINT)id;
111 tvins.item.mask = TVIF_TEXT|TVIF_PARAM;
112 tvins.item.pszText = (WCHAR*)name; //that is ok
113 tvins.item.cchTextMax = strlen(name);
114 tvins.hInsertAfter = TVI_LAST;
115
116 if(icon)
117 {
118 tvins.item.iImage = icon;
119 tvins.item.iSelectedImage = icon;
120 tvins.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE;
121 }
122
123 if (parent==0)
124 tvins.hParent = TVI_ROOT;
125 else
126 tvins.hParent = nodes[parent];
127
128 nodes[id] = (HTREEITEM)SendMessage(hTree, TVM_INSERTITEMA, 0, (LPARAM)&tvins);
129
130 return 0;
131 }
132
133 // Load the Help from file and display it
134 void Help (void)
135 {
136 int i;
137 char buffer [2000];
138 FILE* file = fopen ("help.txt", "r");
139
140 if(!file)
141 return;
142
143 for(i=0; i<2000; i++)
144 {
145 buffer[i] = getc(file);
146 if(buffer[i]==EOF) break;
147 }
148 buffer[i] = 0;
149
150 SetText(buffer);
151 }
152
153 // Create our Controls
154 void InitControls (HWND hwnd)
155 {
156
157 HINSTANCE hinst = GetModuleHandle(NULL);
158 WCHAR errbuf[2000];
159
160 // Create the controls
161 hTree = CreateWindowEx(0, WC_TREEVIEW, L"TreeView", WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS,
162 0, 0, 0, 0, hwnd, NULL, hinst, NULL);
163
164 hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", PML_TransError(IDS_LOAD, (WCHAR*)errbuf, sizeof(errbuf)/sizeof(WCHAR)), WS_CHILD|WS_VISIBLE|ES_MULTILINE,
165 0, 0, 100, 100, hwnd, NULL, hinst, NULL);
166
167 hPopup = LoadMenu(hinst, MAKEINTRESOURCE(IDR_POPUP));
168
169 // Create Tree Icons
170 HIMAGELIST hIcon = ImageList_Create(16,16,ILC_COLOR32,1,1);
171 SendMessage(hTree, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hIcon);
172
173 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(1)));
174 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(11)));
175 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(12)));
176 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(13)));
177 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(14)));
178
179 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(2)));
180 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(3)));
181 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(4)));
182 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(5)));
183 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(6)));
184 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(7)));
185 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(8)));
186 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(9)));
187 ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(10)));
188
189 // Setup Hotkeys
190 hHotKeys = LoadAccelerators (hinst, MAKEINTRESOURCE(IDR_HOTKEYS));
191 }
192
193 // Set the Icons
194 int SetIcon (int id, int icon)
195 {
196 TVITEMEX item;
197
198 item.hItem = nodes[id];
199 item.iImage = icon;
200 item.iSelectedImage = icon;
201 item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
202
203 TreeView_SetItem(hTree, &item);
204
205 return 1;
206 }
207
208 // Set the Icons
209 int Ask (const WCHAR* message)
210 {
211 int ans = MessageBox (0,message,0,MB_YESNO);
212
213 if(ans == IDYES)
214 return 1;
215
216 return 0;
217 }
218
219 // En- or Disable a Button inside of the toolbar and the Context Menu
220 int SetButton (DWORD id, BOOL state)
221 {
222 // Change the Toorbar Button
223 TBBUTTONINFO ti;
224
225 ti.cbSize = sizeof (ti);
226 ti.dwMask = TBIF_STATE;
227
228 if(state)
229 ti.fsState = TBSTATE_ENABLED;
230 else
231 ti.fsState = TBSTATE_INDETERMINATE;
232
233 SendMessage (hTBar, TB_SETBUTTONINFO, id, (LPARAM)&ti);
234
235 // Change the Context Menu item
236 MENUITEMINFO mi;
237
238 mi.cbSize = sizeof (mi);
239 mi.fMask = MIIM_STATE;
240
241 if(state)
242 mi.fState = MFS_ENABLED;
243
244 else
245 mi.fState = MFS_GRAYED;
246
247 SetMenuItemInfo(hPopup, id, FALSE, &mi);
248
249 return 0;
250 }
251
252 // Set the text of the text box
253 int SetText (const char* text)
254 {
255 int i, j;
256 char buffer [2000];
257
258 if(!text)
259 return 1;
260
261 // the windows does not need "\n"
262 // for new lines but "\r\n"
263 for(i=0,j=0; text[i]; i++,j++)
264 {
265 buffer[j] = text[i];
266 if(buffer[j] == '\n')
267 {
268 buffer[j] = '\r';
269 buffer[++j] = '\n';
270 }
271 }
272 buffer[j] = 0;
273
274 SetWindowTextA(hEdit, buffer);
275
276 return 0;
277 }
278
279 // Windows Message Callback (this is where most things happen)
280 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
281 {
282 switch (message)
283 {
284 // at the very beginning ...
285 case WM_CREATE:
286 {
287 InitControls(hwnd);
288 }
289 break;
290
291 // calculate the size of the controls
292 case WM_SIZE:
293 {
294 RECT rcl;
295 SendMessage(hTBar, TB_AUTOSIZE, 0L, 0L);
296 GetWindowRect(hTBar, &rcl);
297
298 int win_top = rcl.bottom - rcl.top;
299 int win_hight = HIWORD(lParam) - win_top;
300
301 MoveWindow(hTree, 0, win_top, LOWORD(lParam), splitter_pos*win_hight/100, TRUE);
302 MoveWindow(hEdit, 0, (splitter_pos*win_hight/100)+win_top, LOWORD(lParam), win_hight, TRUE);
303 }
304 break;
305
306 // for the treeview
307 case WM_NOTIFY:
308 {
309 if(((LPNMHDR)lParam)->code == TVN_SELCHANGED)
310 {
311 selected = ((LPNMTREEVIEW)lParam)->itemNew.lParam;
312 PML_LoadPackage (tree, selected, SetButton);
313 SetText(PML_GetDescription (tree, selected));
314 }
315
316 else if ((int)(((LPNMHDR)lParam)->code) == NM_RCLICK) // <= aarrggg LISP
317 {
318 // which item has been click on
319 HTREEITEM item = TreeView_GetDropHilight(hTree);
320
321 if(item != NULL)
322 {
323 // mark the one as seleacted
324 SendMessage (hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)item);
325 TreeView_EnsureVisible (hTree, item);
326 }
327
328 // create the context menu
329 if(selected != 0)
330 {
331 POINT pt;
332 GetCursorPos (&pt);
333 TrackPopupMenu (GetSubMenu(hPopup, 0), 0, (UINT)pt.x, (UINT)pt.y, 0, hwnd, NULL);
334 }
335 }
336 }
337 break;
338
339 // for the toolbar
340 case WM_COMMAND:
341 {
342 // All Actions
343 if(LOWORD(wParam) <= 5 && LOWORD(wParam) >= 1)
344 {
345 if(selected)
346 if(PML_SetAction(tree, selected, LOWORD(wParam)-1, SetIcon, Ask) == ERR_OK)
347 break;
348
349 MessageBeep(MB_ICONHAND);
350 }
351
352 // DoIt
353 else if(LOWORD(wParam)==6)
354 {
355 if(PML_DoIt(tree, SetStatus, Ask) == ERR_OK)
356 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DOIT), hwnd, StatusProc);
357 else
358 MessageBeep(MB_ICONHAND);
359 }
360
361 // Help
362 else if(LOWORD(wParam)==7)
363 Help();
364
365 // Options
366 else if(LOWORD(wParam)==8)
367 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_OPTIONS), hwnd, OptionsProc);
368 }
369 break;
370
371 // prozess hotkeys
372 case WM_HOTKEY:
373 {
374 if(PML_SetAction(tree, selected, wParam, SetIcon, Ask) != ERR_OK)
375 MessageBeep(MB_ICONHAND);
376 }
377 break;
378
379 // ... at the very end
380 case WM_DESTROY:
381 {
382 PostQuitMessage(0);
383 return 0;
384 }
385 }
386
387 return DefWindowProc (hwnd, message, wParam, lParam);
388 }
389
390 // Warning: This function is called from another thread
391 int SetStatus (int status1, int status2, WCHAR* text)
392 {
393 WCHAR errbuf[2000];
394
395 // Set the Rage to 1000
396 SendMessage(GetDlgItem(hStatus, IDC_STATUS1), PBM_SETRANGE32, 0, 1000);
397 SendMessage(GetDlgItem(hStatus, IDC_STATUS2), PBM_SETRANGE32, 0, 1000);
398
399 // The prozessbars and the text filds
400 if(text)
401 SetDlgItemText(hStatus, IDC_TSTATUS, text);
402
403 if(status1!=-1)
404 SendMessage(GetDlgItem(hStatus, IDC_STATUS1), PBM_SETPOS, status1, 0);
405
406 if(status2!=-1)
407 SendMessage(GetDlgItem(hStatus, IDC_STATUS2), PBM_SETPOS, status2, 0);
408
409 // If the Status is 1000 very thing is done
410 if(status1==1000)
411 {
412 EndDialog(hStatus, TRUE);
413 MessageBox(0,PML_TransError(status2, (WCHAR*)errbuf, sizeof(errbuf)/sizeof(WCHAR)),0,0);
414 }
415
416 return 0;
417 }
418
419 // Callback for the Status Dialog
420 INT_PTR CALLBACK StatusProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
421 {
422 switch (msg)
423 {
424 case WM_INITDIALOG:
425 {
426 hStatus = hwnd;
427
428 } break;
429
430 case WM_COMMAND: // can only be the about button
431 case WM_CLOSE: // the close-window-[x]
432 {
433 PML_Abort();
434 EndDialog(hwnd, TRUE);
435 return 0;
436 }
437 }
438
439 return 0;
440 }
441
442 // Callback for the Options Dialog
443 INT_PTR CALLBACK OptionsProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
444 {
445 switch (msg)
446 {
447 case WM_CLOSE:
448 EndDialog(hwnd, TRUE);
449 return 0;
450 }
451
452 return 0;
453 }