Initial commit.
[amiga/xmodule.git] / ProgressWin.c
1 /*
2 **      ProgressWin.c
3 **
4 **      Copyright (C) 1993,94,95,96 Bernardo Innocenti
5 **
6 **      Parts of this code are:
7 **
8 **      Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
9 **              All Rights Reserved
10 **
11 **      Report status information for an operation in progress.
12 */
13
14 #include <intuition/intuition.h>
15 #include <intuition/gadgetclass.h>
16 #include <libraries/gadtools.h>
17 #include <libraries/asl.h>
18
19 #include <proto/exec.h>
20 #include <proto/dos.h>
21 #include <proto/intuition.h>
22 #include <proto/gadtools.h>
23 #include <proto/graphics.h>
24 #include <proto/layers.h>
25
26 #include "XModulePriv.h"
27 #include "Gui.h"
28
29
30
31 /* Gadgets IDs */
32 enum
33 {
34         GD_ProgressGroup0,
35                 GD_Action,
36                 GD_Percent,
37                 GD_ProgressAbort,
38
39         Progress_CNT
40 };
41
42 enum
43 {
44         GD_LogGroup0,
45                 GD_LogList,
46
47         Log_CNT
48 };
49
50
51 /* Local functions prototypes */
52
53 static void ShowStats                           (struct Gadget *Gadget, LONG Value, LONG Max);
54 static void ProgressAbortClicked        (void);
55 static void LogPostClose                        (void);
56 static LONG ProgressPreOpen                     (struct WinUserData *wud);
57
58
59
60 static UWORD                     LogLines = 0;
61 static UWORD                     ProgressOpenCount = 0;
62 struct List                              LogList;
63 static struct IntuiText  ProgressIT = { 0 };
64 static BOOL                              ProgressAborting = FALSE;
65
66
67
68 static LONG ProgressArgs[] =
69 {
70         TEXT_KIND,              NULL,                                           20,                                                     GTTX_Clipped,   TRUE, TAG_DONE,
71         TEXT_KIND,              NULL,                                           20,                                                     GTTX_Border,    TRUE, TAG_DONE,
72         BUTTON_KIND,    (LONG)ProgressAbortClicked,     MSG_UNDERSCORE_ABORT_GAD,       TAG_DONE,
73         ENDGROUP_KIND
74 };
75
76
77
78 static LONG LogArgs[] =
79 {
80         LISTVIEW_KIND,  NULL,   NULL, (LONG)&LogList,   GTLV_ReadOnly, TRUE, TAG_DONE,
81         ENDGROUP_KIND
82 };
83
84
85
86
87 LONG ProgressWinTags[] =
88 {
89         XMWIN_LayoutArgs,               (LONG)ProgressArgs,
90         XMWIN_GCount,                   Progress_CNT,
91         XMWIN_Title,                    MSG_PROGRESS_TITLE,
92         XMWIN_IDCMPFlags,               BUTTONIDCMP|TEXTIDCMP|IDCMP_REFRESHWINDOW,
93         XMWIN_PostCloseFunc,    (LONG)LogPostClose,
94         TAG_DONE
95 };
96
97
98
99 LONG LogWinTags[] =
100 {
101         XMWIN_LayoutArgs,               (LONG)LogArgs,
102         XMWIN_GCount,                   Log_CNT,
103         XMWIN_Title,                    MSG_LOG_TITLE,
104         XMWIN_WindowFlags,              WFLG_CLOSEGADGET,
105         XMWIN_IDCMPFlags,               LISTVIEWIDCMP|IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW,
106         XMWIN_PreOpenFunc,              (LONG)ProgressPreOpen,
107         TAG_DONE
108 };
109
110
111
112 GLOBALCALL void OpenProgressWindow (void)
113 {
114         ProgressOpenCount++;
115         if (ProgressOpenCount > 1) return;
116
117         LockWindows();
118
119         NewWindow (WID_PROGRESS);
120 }
121
122
123
124 GLOBALCALL void CloseProgressWindow (void)
125 {
126         ProgressOpenCount--;
127         if (ProgressOpenCount) return;
128
129         UnlockWindows ();
130
131         MyCloseWindow (WDescr[WID_PROGRESS].Wud);
132 }
133
134
135
136 static LONG ProgressPreOpen (struct WinUserData *wud)
137 {
138         ProgressIT.FrontPen     = DrawInfo->dri_Pens[FILLTEXTPEN] ? DrawInfo->dri_Pens[FILLTEXTPEN] : DrawInfo->dri_Pens[FILLPEN];
139
140         ProgressIT.DrawMode = (DrawInfo->dri_Pens[FILLPEN] == DrawInfo->dri_Pens[FILLTEXTPEN] || !DrawInfo->dri_Pens[FILLTEXTPEN]) ?
141                 (JAM1 | COMPLEMENT) : (JAM1);
142
143         ProgressIT.ITextFont = wud->Attr;
144
145         return RETURN_OK;
146 }
147
148
149
150 static void LogPostClose (void)
151 {
152         /* Free ListView nodes */
153         while (!IsListEmpty(&LogList))
154                 RemListViewNode (LogList.lh_Head);
155         LogLines = 0;
156 }
157
158
159
160 GLOBALCALL void DisplayAction (ULONG msg)
161
162 /* Tell user what is happening in the Progress window. */
163 {
164         DisplayActionStr (STR(msg));
165 }
166
167
168
169 GLOBALCALL void DisplayActionStr (CONST_STRPTR str)
170
171 /* Tell user what is happening in the Progress window. */
172 {
173         struct WinUserData *wud;
174
175         if ((wud = WDescr[WID_PROGRESS].Wud) && wud->Win)
176                 GT_SetGadgetAttrs (wud->Gadgets[GD_Action], wud->Win, NULL,
177                         GTTX_Text, str,
178                         TAG_DONE);
179 }
180
181
182
183 /* Tell user how are things going.  Also check for abort */
184 GLOBALCALL LONG DisplayProgress (LONG Num, LONG Max)
185 {
186         struct WinUserData *wud;
187
188         if ((wud = WDescr[WID_PROGRESS].Wud) && wud->Win)
189         {
190                 /* Check for CTRL-C Break */
191                 if (SetSignal (0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
192                         return ERROR_BREAK;
193
194
195                 /* Check abort and resizing */
196                 HandleIDCMP();
197
198                 if (ProgressAborting)
199                 {
200                         ProgressAborting = FALSE;
201                         return ERROR_BREAK;
202                 }
203
204                 if (wud->Win)
205                 {
206                         struct Layer_Info       *layerinfo;
207                         UBYTE buf[48];
208
209                         /* Attempt to lock the LayerInfo associated with the
210                          * screen where the Progress window resides in.
211                          *
212                          * We do this to prevent blocking the operation in progress
213                          * when someone else (e.g. Intuition) is keeping the lock.
214                          *
215                          * Note that there is no AttemptLockLayerInfo() function
216                          * and LockLayerInfo() will wait if the layer is already
217                          * locked, which is exactly what we are trying to avoid.
218                          *
219                          * Our workaround is checking the LockLayersCount before
220                          * locking the LayerInfo.
221                          *
222                          * TODO: Experiment with AttemptLockLayerRom().
223                          */
224
225                         /* Perhaps using Scr->LayerInfo would be the same */
226                         layerinfo = wud->Win->RPort->Layer->LayerInfo;
227
228                         Forbid();
229                         if (!layerinfo->LockLayersCount)
230                         {
231                                 struct Gadget *g;
232
233                                 LockLayerInfo (layerinfo);
234                                 Permit();
235
236                                 g = wud->Gadgets[GD_Percent];
237
238                                 /* Update Stats */
239                                 ShowStats (g, Num, Max);
240
241                                 /* Display progress string */
242
243                                 SPrintf (buf, STR(MSG_PERCENT_DONE), Num, Max, (Num * 100) / Max);
244
245                                 ProgressIT.IText = buf;
246
247                                 PrintIText (wud->Win->RPort, &ProgressIT,
248                                         g->LeftEdge + 2 + (g->Width - 4 - IntuiTextLength (&ProgressIT)) / 2,
249                                         g->TopEdge + 1 + (g->Height - 2 - wud->Win->RPort->TxHeight) / 2);
250
251                                 UnlockLayerInfo (layerinfo);
252                         }
253                         else Permit();
254                 }
255         }
256
257         return FALSE;
258 }
259
260
261
262 static void ShowStats (struct Gadget *Gadget, LONG Value, LONG Max)
263
264 /* Show the percentage bars. */
265 {
266         struct RastPort *RPort = WDescr[WID_PROGRESS].Wud->Win->RPort;
267         LONG    MaxWidth = Gadget->Width - 4,
268                         Width;
269
270
271         if (Max < 1)            Max = 0;
272         if (Value > Max)        Value = Max;
273
274
275         if((Width = (MaxWidth * Value) / Max) > 0)
276         {
277                 if(Width != MaxWidth)
278                 {
279                         SetAPen (RPort,0);
280                         RectFill (RPort, Gadget->LeftEdge + 2 + Width - 1, Gadget->TopEdge + 1,
281                                 Gadget->LeftEdge + Gadget->Width - 3, Gadget->TopEdge + Gadget->Height - 2);
282                 }
283
284                 SetAPen (RPort, DrawInfo->dri_Pens[FILLPEN]);
285                 RectFill (RPort,Gadget->LeftEdge + 2,Gadget->TopEdge + 1,
286                         Gadget->LeftEdge + Width + 1, Gadget->TopEdge + Gadget->Height - 2);
287         }
288         else
289         {
290                 SetAPen (RPort, 0);
291                 RectFill (RPort, Gadget->LeftEdge + 2, Gadget->TopEdge + 1,
292                         Gadget->LeftEdge + Gadget->Width - 3, Gadget->TopEdge + Gadget->Height - 2);
293         }
294 }
295
296
297
298
299 GLOBALCALL void ShowMessage (ULONG msg, ...)
300
301 /* Localized interface to ShowString(). */
302 {
303         ShowString (STR(msg), (LONG *)(&msg+1));
304 }
305
306
307 GLOBALCALL void ShowString (CONST_STRPTR s, LONG *args)
308
309 /* Formats a string and shows it to the user in the Log Window.
310  * If the Log Window can't be opened, this function will fall
311  * to ShowRequest() or to Printf().
312  */
313 {
314         struct WinUserData *wud;
315
316         if (!IntuitionBase)
317         {
318                 if (StdOut) VPrintf ((STRPTR)s, args);
319                 return;
320         }
321
322         wud = WDescr[WID_LOG].Wud;
323
324         if (!wud || !wud->Win)
325         {
326                 NewWindow (WID_LOG);
327                 wud = WDescr[WID_LOG].Wud;
328         }
329
330         if (wud && wud->Win)
331         {
332                 GT_SetGadgetAttrs (wud->Gadgets[GD_LogList], wud->Win, NULL,
333                         GTLV_Labels, ~0,
334                         TAG_DONE);
335
336                 if (LogLines > 30)
337                 {
338                         RemListViewNode (LogList.lh_Head);
339                         LogLines--;
340                 }
341
342                 if (AddListViewNodeA (&LogList, s, args))
343                         LogLines++;
344                 else
345                         DisplayBeep(Scr);
346
347                 GT_SetGadgetAttrs (wud->Gadgets[GD_LogList], wud->Win, NULL,
348                         GTLV_Labels, &LogList,
349                         GTLV_Top, 30,
350                         TAG_DONE);
351         }
352         else
353                 ShowRequestStr (s, NULL, args);
354 }
355
356
357
358 static void ProgressAbortClicked (void)
359 {
360         ProgressAborting = TRUE;
361 }