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