win32-name-event-objects-20040228
[openafs.git] / src / WINNT / afssvrmgr / svr_window.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include "svrmgr.h"
16 #include "svr_window.h"
17 #include "propcache.h"
18 #include "set_tab.h"
19 #include "agg_tab.h"
20 #include "svc_tab.h"
21 #include "display.h"
22 #include "command.h"
23
24
25 /*
26  * RESIZING WINDOWS ___________________________________________________________
27  *
28  */
29
30 #define cxMIN_SERVER 100
31 #define cyMIN_SERVER 100
32
33 static rwWindowData awdServer[] = {
34     { IDC_TABS,  raSizeX | raSizeY,     MAKELONG(cxMIN_SERVER,cyMIN_SERVER),    0 },
35     { idENDLIST, 0,                     0,                                      0 }
36  };
37
38 static rwWindowData awdTabChild[] = {
39     { 0,         raSizeX | raSizeY,     0,      0 },
40     { idENDLIST, 0,                     0,      0  }
41  };
42
43
44 /*
45  * CHILD TABS _________________________________________________________________
46  *
47  */
48
49 static struct // CHILDTABINFO
50    {
51    CHILDTAB tab;
52    int idsTabTitle;
53    int iImage;
54    }
55 CHILDTABINFO[] =
56    {
57       { tabFILESETS,   IDS_TAB_FILESETS,   imageFILESET   },
58       { tabAGGREGATES, IDS_TAB_AGGREGATES, imageAGGREGATE },
59       { tabSERVICES,   IDS_TAB_SERVICES,   imageSERVICE   },
60    };
61
62 #define nCHILDTABS (sizeof(CHILDTABINFO)/sizeof(CHILDTABINFO[0]))
63
64
65
66 /*
67  * PROTOTYPES _________________________________________________________________
68  *
69  */
70
71 BOOL CALLBACK Server_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
72
73 void Server_SaveRect (HWND hDlg, BOOL fOpen);
74
75 BOOL Server_HandleDialogKeys (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
76
77
78 /*
79  * ROUTINES ___________________________________________________________________
80  *
81  */
82
83 void Server_Open (LPIDENT lpiServer, LPRECT prWindow)
84 {
85    HWND hServer;
86
87    if ((hServer = PropCache_Search (pcSERVER, lpiServer)) != NULL)
88       {
89       SetFocus (hServer);
90       }
91    else
92       {
93       // First off, if this server isn't being monitored, we have
94       // to start monitoring it or we can't open a window (nothing to
95       // show otherwise).
96       //
97       LPSERVER_PREF lpsp;
98       if ((lpsp = (LPSERVER_PREF)lpiServer->GetUserParam()) != NULL)
99          {
100          BOOL fCanShowWindow = (gr.fOpenMonitors || lpsp->fIsMonitored);
101
102          if (gr.fOpenMonitors && !lpsp->fIsMonitored)
103             {
104             StartTask (taskSVR_MONITOR_ONOFF, NULL, lpiServer);
105             }
106
107          if (fCanShowWindow)
108             {
109             hServer = ModelessDialogParam (IDD_SERVER, NULL, (DLGPROC)Server_DlgProc, (LPARAM)lpiServer);
110             Server_SelectServer (hServer, lpiServer);
111
112             if (prWindow->right != 0)
113                {
114                SetWindowPos (hServer, NULL, prWindow->left, prWindow->top,
115                              cxRECT(*prWindow), cyRECT(*prWindow),
116                              SWP_NOZORDER | SWP_NOACTIVATE);
117                }
118
119             ShowWindow (hServer, SW_NORMAL);
120             }
121          }
122       }
123 }
124
125
126 void Server_Close (LPIDENT lpiServer)
127 {
128    HWND hWnd;
129
130    if ((hWnd = PropCache_Search (pcSERVER, lpiServer)) != NULL)
131       {
132       Server_SaveRect (hWnd, FALSE);
133       DestroyWindow (hWnd);
134
135       // If there's a subset active, the user may want us to stop
136       // monitoring this server once its window is closed.
137       //
138       LPSERVER_PREF lpsp;
139       if ((lpsp = (LPSERVER_PREF)lpiServer->GetUserParam()) != NULL)
140          {
141          if (g.sub && gr.fCloseUnmonitors && lpsp->fIsMonitored && !gr.fPreview)
142             {
143             StartTask (taskSVR_MONITOR_ONOFF, NULL, lpiServer);
144             }
145          }
146       }
147 }
148
149
150 void Server_CloseAll (BOOL fUserRequested)
151 {
152    HWND hWnd;
153
154    while ((hWnd = PropCache_Search (pcSERVER, ANYVALUE)) != NULL)
155       {
156       LPIDENT lpiServer = Server_GetServer (hWnd);
157
158       Server_SaveRect (hWnd, !fUserRequested);
159       DestroyWindow (hWnd);
160
161       if (lpiServer && fUserRequested)
162          {
163          // If there's a subset active, the user may want us to stop
164          // monitoring this server once its window is closed.
165          //
166          LPSERVER_PREF lpsp;
167          if ((lpsp = (LPSERVER_PREF)lpiServer->GetUserParam()) != NULL)
168             {
169             if (g.sub && gr.fCloseUnmonitors && lpsp->fIsMonitored)
170                {
171                StartTask (taskSVR_MONITOR_ONOFF, NULL, lpiServer);
172                }
173             }
174          }
175       }
176 }
177
178
179 HWND Server_GetCurrentTab (HWND hWnd)
180 {
181    return GetTabChild (GetDlgItem (hWnd, IDC_TABS));
182 }
183
184 CHILDTAB Server_GetDisplayedTab (HWND hWnd)
185 {
186    HWND hTabs = GetDlgItem (hWnd, IDC_TABS);
187    return (hTabs) ? (CHILDTAB)TabCtrl_GetCurSel(hTabs) : tabINVALID;
188 }
189
190 HWND Server_GetWindowForChild (HWND hChild)
191 {
192    // hChild is the Filesets_DlgProc dialog (or whatever)
193    // Its parent is the tab control on the server window
194    // Its grandparent is the Popup HWND (may be g.hMain) that we want.
195    //
196    return GetParent (GetParent (hChild));
197 }
198
199 void Server_SelectServer (HWND hDlg, LPIDENT lpiNew, BOOL fForceRedraw)
200 {
201    LPIDENT lpiOld = Server_GetServer (hDlg);
202    if (lpiNew != lpiOld)
203       {
204       SetWindowLong (hDlg, DWL_USER, (LONG)lpiNew);
205
206       if (hDlg != g.hMain)
207          {
208          if (lpiOld)
209             PropCache_Delete (pcSERVER, lpiOld);
210
211          if (lpiNew)
212             {
213             PropCache_Add (pcSERVER, lpiNew, hDlg);
214
215             TCHAR szName[ cchNAME ];
216             lpiNew->GetServerName (szName);
217             LPTSTR pszTitle = FormatString (IDS_SERVER_TITLE, TEXT("%s"), szName);
218             SetWindowText (hDlg, pszTitle);
219             FreeString (pszTitle);
220             }
221          }
222
223       fForceRedraw = TRUE;
224       }
225
226    if (fForceRedraw)
227       {
228       Server_ForceRedraw (hDlg);
229       }
230 }
231
232 LPIDENT Server_GetServer (HWND hDlg)
233 {
234    return (LPIDENT)GetWindowLong (hDlg, DWL_USER);
235 }
236
237 LPIDENT Server_GetServerForChild (HWND hChild)
238 {
239    if (GetParent(hChild) == NULL)
240       return Server_GetServer (hChild);
241    else
242       return Server_GetServer (GetParent(GetParent(hChild)));
243 }
244
245
246 void Server_ForceRedraw (HWND hDlg)
247 {
248    HWND hChild = Server_GetCurrentTab (hDlg);
249
250    if (hChild && IsWindow (hChild))
251       {
252       PostMessage (hChild, WM_SERVER_CHANGED, 0, 0);
253       }
254 }
255
256
257 /*
258  * SERVER DIALOG ______________________________________________________________
259  *
260  */
261
262 BOOL CALLBACK Server_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
263 {
264    LPIDENT lpiServer = Server_GetServer (hDlg);
265
266    if (Server_HandleDialogKeys (hDlg, msg, wp, lp))
267       return TRUE;
268
269    switch (msg)
270       {
271       case WM_INITDIALOG:
272          RECT rWindow;
273          Server_PrepareTabControl (GetDlgItem (hDlg, IDC_TABS));
274          GetWindowRect (hDlg, &rWindow);
275          ResizeWindow (hDlg, awdServer, rwaMoveToHere, &rWindow);
276          break;
277
278       case WM_HELP:
279          WinHelp (hDlg, cszHELPFILENAME, HELP_FINDER, 0);
280          break;
281
282       case WM_DESTROY:
283          GetWindowRect (hDlg, &gr.rServerLast);
284
285          if (lpiServer)
286             PropCache_Delete (pcSERVER, lpiServer);
287          break;
288
289       case WM_SIZE:
290          // if (lp==0), we're minimizing--don't call ResizeWindow().
291          //
292          if (lp != 0)
293             {
294             ResizeWindow (hDlg, awdServer, rwaFixupGuts);
295             Server_SaveRect (hDlg, TRUE);
296             }
297          break;
298
299       case WM_MOVE:
300          Server_SaveRect (hDlg, TRUE);
301          break;
302
303       case WM_SETFOCUS:
304          gr.tabLast = Server_GetDisplayedTab (hDlg);
305          break;
306
307       case WM_COMMAND:
308          switch (LOWORD(wp))
309             {
310             case IDCANCEL:
311                LPIDENT lpi;
312                if ((lpi = Server_GetServer (hDlg)) != NULL)
313                   Server_Close (lpi);
314                else
315                   DestroyWindow (hDlg);
316                break;
317             }
318          break;
319
320       case WM_NOTIFY: 
321          switch (((LPNMHDR)lp)->code)
322             { 
323             case TCN_SELCHANGE:
324                { 
325                HWND hTab = GetDlgItem (hDlg, IDC_TABS);
326                int iPage = TabCtrl_GetCurSel (hTab); 
327
328                Server_DisplayTab (hDlg, (CHILDTAB)iPage);
329                gr.tabLast = (CHILDTAB)iPage;
330                }
331                break;
332             }
333          break;
334       }
335
336    return FALSE;
337 }
338
339
340 static LONG procTabControl = 0;
341
342 LRESULT CALLBACK Server_SubclassTabControlProc (HWND hTab, UINT msg, WPARAM wp, LPARAM lp)
343 {
344    LRESULT rc;
345
346    if (procTabControl == 0)
347       rc = DefWindowProc (hTab, msg, wp, lp);
348    else
349       rc = CallWindowProc ((WNDPROC)procTabControl, hTab, msg, wp, lp);
350
351    switch (msg)
352       {
353       // Since this is a subclass proc, it's not around when the window
354       // is created.  Any WM_CREATE processing we'd ordinarily do here
355       // must therefore be done at the point where the tab control is
356       // subclassed.
357       //
358       // case WM_CREATE:
359
360       case WM_SIZE:
361          if (lp != 0)
362             ResizeWindow (hTab, awdTabChild, rwaFixupGuts);
363          break;
364
365       case WM_DESTROY:
366          if (procTabControl != 0)
367             SetWindowLong (hTab, GWL_WNDPROC, procTabControl);
368          break;
369       }
370
371    return rc;
372 }
373
374
375 void Server_PrepareTabControl (HWND hTab)
376 {
377    TabCtrl_SetImageList (hTab, AfsAppLib_CreateImageList (FALSE));
378
379    TCHAR szText[ cchRESOURCE ];
380    TC_ITEM tci;
381    tci.mask = TCIF_TEXT | TCIF_PARAM | TCIF_IMAGE;
382    tci.pszText = szText;
383
384    for (int iTab = 0; iTab < nCHILDTABS; ++iTab)
385       {
386       tci.iImage = CHILDTABINFO[ iTab ].iImage;
387       tci.lParam = (LPARAM)CHILDTABINFO[ iTab ].tab;
388       GetString (tci.pszText, CHILDTABINFO[ iTab ].idsTabTitle);
389       TabCtrl_InsertItem (hTab, iTab, &tci);
390       }
391
392    // subclass the TCN_ window, so that it will start sending WM_SIZE
393    // messages to its child window.
394    //
395    procTabControl = GetWindowLong (hTab, GWL_WNDPROC);
396    SetWindowLong (hTab, GWL_WNDPROC, (LONG)Server_SubclassTabControlProc);
397
398    // Since we just subclassed this control, our new wndproc wasn't around
399    // when the window was created.  Any WM_CREATE processing we'd ordinarily
400    // in that wndproc must therefore be done here.
401
402    // WM_CREATE:
403    RECT rWindow;
404    GetRectInParent (hTab, &rWindow);
405    ResizeWindow (hTab, awdTabChild, rwaMoveToHere, &rWindow);
406
407    // Finally, select an appropriate tab and display it.
408    //
409    Server_DisplayTab (GetParent (hTab), gr.tabLast);
410 }
411
412
413 void Server_DisplayTab (HWND hDlg, CHILDTAB iTab)
414 {
415    HWND hTab = GetDlgItem (hDlg, IDC_TABS);
416    int idd = -1;
417    DLGPROC dlgproc = NULL;
418
419    switch (iTab)
420       {
421       case tabSERVICES:
422          idd = IDD_SERVICES;
423          dlgproc = (DLGPROC)Services_DlgProc;
424          break;
425       case tabAGGREGATES:
426          idd = IDD_AGGREGATES;
427          dlgproc = (DLGPROC)Aggregates_DlgProc;
428          break;
429       case tabFILESETS:
430          idd = IDD_FILESETS;
431          dlgproc = (DLGPROC)Filesets_DlgProc;
432          break;
433       }
434
435    if (idd != -1)
436       {
437       HWND hDialogOld = GetTabChild (hTab);
438       HWND hDialogNew = ModelessDialog (idd, hTab, dlgproc);
439
440       if (hDialogNew != NULL)
441          {
442          TabCtrl_SetCurSel (hTab, iTab);
443          ShowWindow (hDialogNew, SW_SHOW);
444
445          if (hDialogOld != NULL)
446             {
447             DestroyWindow (hDialogOld);
448             }
449
450          Server_ForceRedraw (hDlg);
451          }
452       }
453 }
454
455
456 void Server_Uncover (HWND hWnd)
457 {
458    if (hWnd == g.hMain) // uncover the preview pane?
459       {
460       AfsAppLib_Uncover (GetDlgItem (g.hMain, IDC_TABS));
461       }
462    else // uncover a standalone server window?
463       {
464       AfsAppLib_Uncover (hWnd);
465       }
466 }
467
468
469 void Server_SaveRect (HWND hDlg, BOOL fOpen)
470 {
471    LPSVR_SETWINDOWPOS_PARAMS lpp = New (SVR_SETWINDOWPOS_PARAMS);
472    GetWindowRect (hDlg, &lpp->rWindow);
473    lpp->lpi = Server_GetServer (hDlg);
474    lpp->fOpen = fOpen;
475
476    StartTask (taskSVR_SETWINDOWPOS, NULL, lpp);
477 }
478
479
480 BOOL Server_HandleDialogKeys (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
481 {
482    if (msg == WM_COMMAND)
483       {
484       switch (LOWORD(wp))
485          {
486          case M_KEY_RETURN:
487             Server_OnKey_Return();
488             return TRUE;
489
490          case M_KEY_CTRLTAB:
491             Server_OnKey_CtrlTab (hDlg, TRUE);
492             return TRUE;
493
494          case M_KEY_CTRLBACKTAB:
495             Server_OnKey_CtrlTab (hDlg, FALSE);
496             return TRUE;
497
498          case M_KEY_TAB:
499             Server_OnKey_Tab (hDlg, TRUE);
500             return TRUE;
501
502          case M_KEY_BACKTAB:
503             Server_OnKey_Tab (hDlg, FALSE);
504             return TRUE;
505
506          case M_KEY_MENU:
507             Server_OnKey_Menu();
508             return TRUE;
509
510          case M_KEY_ESC:
511             Server_OnKey_Esc();
512             return TRUE;
513
514          case M_KEY_PROPERTIES:
515             Server_OnKey_Properties();
516             return TRUE;
517          }
518       }
519
520    return FALSE;
521 }
522
523
524 void Server_OnKey_Return (void)
525 {
526    static NMHDR hdr;
527    hdr.hwndFrom = GetFocus();
528    hdr.idFrom = GetWindowLong (GetFocus(), GWL_ID);
529    hdr.code = FLN_LDBLCLICK;
530    PostMessage (GetParent (GetFocus()), WM_NOTIFY, 0, (LPARAM)&hdr);
531 }
532
533
534 void Server_OnKey_Menu (void)
535 {
536    HWND hFocus = GetFocus();
537    if (fIsFastList (hFocus))
538       {
539       POINT ptScreen = { 0, 0 };
540
541       HLISTITEM hItem;
542       if ((hItem = FastList_FindFirstSelected (hFocus)) != NULL)
543          {
544          FASTLISTITEMREGIONS reg;
545          FastList_GetItemRegions (hFocus, hItem, &reg);
546
547          ptScreen.x = reg.rItem.left + (reg.rItem.right -reg.rItem.left) /2;
548          ptScreen.y = reg.rItem.top + (reg.rItem.bottom -reg.rItem.top) /2;
549          ClientToScreen (GetFocus(), &ptScreen);
550          }
551
552       PostMessage (GetParent (GetFocus()), WM_CONTEXTMENU, (WPARAM)GetFocus(), MAKELONG(ptScreen.x,ptScreen.y));
553       }
554 }
555
556
557 void Server_OnKey_Esc (void)
558 {
559    HWND hFocus = GetFocus();
560    if (fIsFastList (hFocus))
561       {
562       FastList_SelectNone (hFocus);
563       }
564 }
565
566
567 void Server_OnKey_Properties (void)
568 {
569    HWND hFocus = GetFocus();
570    if (fIsFastList (hFocus))
571       {
572       LPIDENT lpi;
573       if ((lpi = (LPIDENT)FL_GetSelectedData (hFocus)) != NULL)
574          {
575          StartContextCommand (GetParent(hFocus), NULL, lpi, M_PROPERTIES);
576          }
577       }
578 }
579
580
581 void Server_OnKey_Tab (HWND hDlg, BOOL fForward)
582 {
583    // The tab-cycle should go:
584    //    TabControl <-> TabChildControls
585    //
586    HWND hFocus = GetFocus();
587    HWND hTabChild = GetTabChild (GetDlgItem (hDlg, IDC_TABS));
588
589    if (fForward)
590       {
591       if (hFocus == GetDlgItem (hDlg, IDC_TABS))
592          {
593          PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetNextDlgTabItem (hTabChild, NULL, FALSE), TRUE);
594          }
595       else
596          {
597          if (GetNextDlgTabItem (hTabChild, hFocus, FALSE) == GetNextDlgTabItem (hTabChild, NULL, FALSE))
598             PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem (hDlg, IDC_TABS), TRUE);
599          else
600             PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetNextDlgTabItem (hTabChild, hFocus, FALSE), TRUE);
601          }
602       }
603    else // (!fForward)
604       {
605       if (hFocus == GetDlgItem (hDlg, IDC_TABS))
606          {
607          PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetLastDlgTabItem (hTabChild), TRUE);
608          }
609       else
610          {
611          if (hFocus == GetNextDlgTabItem (hTabChild, NULL, FALSE))
612             PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem (hDlg, IDC_TABS), TRUE);
613          else
614             PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetNextDlgTabItem (hTabChild, hFocus, TRUE), TRUE);
615          }
616       }
617 }
618
619
620 void Server_OnKey_CtrlTab (HWND hDlg, BOOL fForward)
621 {
622    HWND hTabs = GetDlgItem (hDlg, IDC_TABS);
623    int iTab = TabCtrl_GetCurSel(hTabs);
624
625    if (fForward)
626       iTab = (iTab == nCHILDTABS-1) ? (0) : (iTab+1);
627    else
628       iTab = (iTab == 0) ? (nCHILDTABS-1) : (iTab-1);
629
630    TabCtrl_SetCurSel (hTabs, iTab);
631    Server_DisplayTab (hDlg, (CHILDTAB)iTab);
632    gr.tabLast = (CHILDTAB)iTab;
633
634    PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)hTabs, TRUE);
635 }
636