-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStdGadgetStatusBar.cpp
515 lines (386 loc) · 14.4 KB
/
StdGadgetStatusBar.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
#include "StdFuncs.h"
#include <string.h>
#include "StdGadgets.h"
#include "StdReaction.h"
#include "StdWindow.h"
#ifdef __amigaos__
#include <gadgets/layout.h>
#elif defined(QT_GUI_LIB)
#include <QtWidgets/QLabel>
#include <QtWidgets/QStatusBar>
#include "Qt/QtWindow.h"
#elif defined(WIN32)
#include <commctrl.h>
#endif /* WIN32 */
#ifdef __amigaos__
#define MAX_CHARS 255
#endif /* __amigaos__ */
/**
* Create a new instance of the CStdGadgetStatusBar class.
* Creates an intance of the status bar gadget and attaches it to the parent layout specified.
* The a_piPartsOffsets array is reused for calculating the sizes of the parts and its contents
* are no longer required on return.
*
* @date Sunday 01-May-2011 7:10 am
* @param a_poParentLayout Pointer to the gadget layout that will hold this gadget
* @param a_iNumParts Number of parts to be created
* @param a_piPartsOffsets Ptr to array of sizes of parts as percentages
* @param a_iGadgetID Unique identifier of the status bar gadget Must be > 0
* @return Pointer to the newly created status bar if successful, else NULL
*/
CStdGadgetStatusBar *CStdGadgetStatusBar::New(CStdGadgetLayout *a_poParentLayout, TInt a_iNumParts,
TInt *a_piPartsOffsets, TInt a_iGadgetID)
{
CStdGadgetStatusBar *RetVal;
ASSERTM((a_iGadgetID > 0), "CStdGadgetStatusBar::New() => Gadget ID must be > 0");
if ((RetVal = new CStdGadgetStatusBar(a_poParentLayout, a_iGadgetID)) != NULL)
{
if (RetVal->Construct(a_iNumParts, a_piPartsOffsets) != KErrNone)
{
delete RetVal;
RetVal = NULL;
}
}
return(RetVal);
}
/* Written: Friday 29-Apr-2011 3:45 pm */
/* @param a_iNumParts Number of parts to be created */
/* a_piPartsOffsets Ptr to array of sizes of parts as percentages */
/* @return KErrNone if successful, else KErrNoMemory */
/* Initialises an intance of the status bar gadget and attaches it to the parent window specified. */
/* The a_piPartsOffsets array is reused for calculating the sizes of the parts and so is no */
/* longer valid on return */
TInt CStdGadgetStatusBar::Construct(TInt a_iNumParts, TInt *a_piPartsOffsets)
{
TInt Index, RetVal;
/* Assume failure */
RetVal = KErrNoMemory;
#ifdef __amigaos__
/* Create a horizontal layout group into which can be placed the parts labels */
if ((m_poGadget = (Object *) NewObject(LAYOUT_GetClass(), NULL, LAYOUT_Orientation, LAYOUT_HORIZONTAL, LAYOUT_FixedVert, FALSE, TAG_DONE)) != NULL)
{
/* Create an array of ptrs into which we can place the ptrs to the parts labels in order */
/* to access them l8r on, and create a part label for each slot in the array */
if ((m_poPartsGadgets = new Object *[a_iNumParts]) != NULL)
{
/* Create a string gadget for each part requested by the user */
for (Index = 0; Index < a_iNumParts; ++Index)
{
m_poPartsGadgets[Index] = NewObject(STRING_GetClass(), NULL, STRINGA_MaxChars, MAX_CHARS, GA_ReadOnly, TRUE, TAG_DONE);
if (m_poPartsGadgets[Index])
{
/* Add the string gadget to the horizontal layout group, with the desired weighting */
SetGadgetAttrs((struct Gadget *) m_poGadget, m_poParentWindow->m_poWindow, NULL, LAYOUT_AddChild,
(ULONG) m_poPartsGadgets[Index], CHILD_WeightedWidth, (ULONG) a_piPartsOffsets[Index], TAG_DONE);
}
else
{
Utils::info("CStdGadgetStatusBar::Construct() => Unable to create status bar label gadget");
break;
}
}
/* If all parts labels were created ok then indicate success. On failure the individual */
/* String gadgets used for the parts do not need to be destroyed as they have been added */
/* to the Layout gadget representing the status bar and will be automatically destroyed */
/* when the Layout gadget is destroyed below */
if (Index == a_iNumParts)
{
RetVal = KErrNone;
m_iNumParts = a_iNumParts;
}
}
else
{
Utils::info("CStdGadgetStatusBar::Construct() => Out of memory");
}
}
else
{
Utils::info("CStdGadgetStatusBar::Construct() => Unable to create status bar group gadget");
}
/* If anything went wrong then clean up whatever was successfully allocated */
if (RetVal != KErrNone)
{
if (m_poGadget)
{
DisposeObject(m_poGadget);
m_poGadget = NULL;
}
if (m_poPartsGadgets)
{
delete [] m_poPartsGadgets;
m_poPartsGadgets = NULL;
}
}
#elif defined(QT_GUI_LIB)
QStatusBar *StatusBar;
if ((StatusBar = new QStatusBar()) != NULL)
{
/* Create a style sheet and assign it to the status bar, to ensure that it looks */
/* half decent and is actually usable. Without this it is almost invisible! */
QString styleSheet = "\
QStatusBar {\
background : #f2f1f0;\
}\
\
QStatusBar::item {\
border : 1px solid #c9c6c3;\
border-radius: 3px;\
}\
";
StatusBar->setStyleSheet(styleSheet);
/* Create an array of ptrs into which we can place the ptrs to the parts labels in order */
/* to access them l8r on, and create a part label for each slot in the array */
if ((m_poPartsGadgets = new QLabel *[a_iNumParts]) != NULL)
{
/* Create a QLabel gadget for each part requested by the user */
for (Index = 0; Index < a_iNumParts; ++Index)
{
m_poPartsGadgets[Index] = new QLabel();
if (m_poPartsGadgets[Index])
{
/* Add the QLabel gadget to the QStatusBar belonging to the window */
StatusBar->addWidget(m_poPartsGadgets[Index], a_piPartsOffsets[Index]);
}
else
{
break;
}
}
/* If all parts labels were created successfully then indicate success and attach the */
/* status bar to the parent layout */
if (Index == a_iNumParts)
{
RetVal = KErrNone;
/* Save the pointer to the status bar and information about it for later */
m_poGadget = StatusBar;
m_iNumParts = a_iNumParts;
// TODO: CAW (multi)
m_iHeight = 30;//StatusBar->height();
}
/* Otherwise destroy whatever labels were created. The labels belong to the */
/* window's status bar and will be disposed of when it is destroyed, but we don't */
/* want them left attached because if a new CStdGadgetStatusBar gadget is l8r on */
/* created successfully then the window will also contain these old QLabel objects */
else
{
while (--Index >= 0)
{
delete m_poPartsGadgets[Index];
}
}
}
}
/* If anything went wrong then clean up whatever was successfully allocated */
if (RetVal != KErrNone)
{
delete [] m_poPartsGadgets;
m_poPartsGadgets = NULL;
delete StatusBar;
}
#else /* ! QT_GUI_LIB */
TInt Offset, ParentWidth;
RECT Rect;
/* Register the status bar window control class so that we can use it */
InitCommonControls();
/* Create the underlying Windows control */
m_poGadget = CreateWindowEx(0, STATUSCLASSNAME, NULL, (SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE),
0, 0, 0, 0, m_poParentWindow->m_poWindow, NULL, NULL, NULL);
if (m_poGadget)
{
/* Create a copy of the offset array for use if the window is resized, in which case the positions */
/* of the parts need to be recalculated based on the new size */
if ((m_piPartsOffsets = new TInt[a_iNumParts]) != NULL)
{
memcpy(m_piPartsOffsets, a_piPartsOffsets, (a_iNumParts * sizeof(TInt)));
/* Convert the parts offsets from percentages to pixel widths as required by the underlying */
/* Windows control */
Offset = 0;
ParentWidth = m_poParentWindow->InnerWidth();
for (Index = 0; Index < a_iNumParts; ++Index)
{
a_piPartsOffsets[Index] = (int) (Offset + (a_piPartsOffsets[Index] / 100.0f * ParentWidth));
Offset = a_piPartsOffsets[Index];
}
/* Subdivide the status bar into the requested number of parts at the requested positions */
if (SendMessage(m_poGadget, SB_SETPARTS, a_iNumParts, (LPARAM) a_piPartsOffsets))
{
m_iNumParts = a_iNumParts;
/* And determine the dimensions of the gadget and save them for l8r */
if (GetClientRect(m_poGadget, &Rect))
{
RetVal = KErrNone;
m_iWidth = (Rect.right - Rect.left);
m_iHeight = m_iMinHeight = (Rect.bottom - Rect.top);
}
else
{
Utils::info("CStdGadgetStatusBar::Construct() => Unable to determine size of status bar");
}
}
else
{
Utils::info("CStdGadgetStatusBar::Construct() => Unable to subdivide status bar into parts");
}
}
}
else
{
Utils::info("CStdGadgetStatusBar::Construct() => Unable to create status bar");
}
#endif /* ! QT_GUI_LIB */
/* If the platform specific gadget was successfully created, finish the generic initialisation and */
/* attach it to the parent layout */
if (RetVal == KErrNone)
{
/* Allocate an array of ptrs to be used for storing the content of the parts */
if ((m_ppcPartsText = new char *[a_iNumParts]) != NULL)
{
/* And attach the gadget */
m_poParentLayout->Attach(this);
}
else
{
Utils::info("CStdGadgetStatusBar::Construct() => Out of memory");
}
}
return(RetVal);
}
/**
* CStdGadgetStatusBar destructor.
* Deletes all gadgets used for displaying the status bar, and/or the text associated
* with them.
*
* @date Monday 02-May-2011 7:21 am, Code HQ-by-Thames
*/
CStdGadgetStatusBar::~CStdGadgetStatusBar()
{
int Index;
#ifdef __amigaos__
delete [] m_poPartsGadgets;
#elif defined(QT_GUI_LIB)
/* Iterate through the parts widgets attached to the system status bar and delete them */
for (Index = 0; Index < m_iNumParts; ++Index)
{
if (m_poPartsGadgets[Index])
{
delete m_poPartsGadgets[Index];
}
}
delete [] m_poPartsGadgets;
delete m_poGadget;
#else /* ! QT_GUI_LIB */
if (m_poGadget)
{
DEBUGCHECK((DestroyWindow(m_poGadget) != FALSE), "CStdGadgetStatusBar::~CStdGadgetStatusBar() => Cannot destroy native status bar gadget");
}
delete [] m_piPartsOffsets;
#endif /* ! QT_GUI_LIB */
/* Free the content of the parts, if allocated */
if (m_ppcPartsText)
{
for (Index = 0; Index < m_iNumParts; ++Index)
{
Utils::FreeTempBuffer(m_ppcPartsText[Index]);
}
delete [] m_ppcPartsText;
}
}
/* Written: Tuesday 20-Mar-2011 8:04 am, Hilton Košice */
/* @param a_iPart Index of part of the status bar from which to obtain the text */
/* @return Ptr to the text from the status bar if it has been set, else an empty string */
/* Gets the content of the specified subpart of the status bar. The text is cached so this */
/* is a very fast function to call. */
const char *CStdGadgetStatusBar::GetText(TInt a_iPart)
{
const char *RetVal;
ASSERTM((a_iPart < m_iNumParts), "CStdGadgetStatusBar::GetText() => Part # is out of range");
ASSERTM((m_ppcPartsText != NULL), "CStdGadgetStatusBar::GetText() => Gadget not initialised");
/* Retrieve the text from our saved copy, rather than relying on the underlying */
/* operating system to give it to us */
RetVal = (m_ppcPartsText[a_iPart]) ? m_ppcPartsText[a_iPart] : "";
return(RetVal);
}
/**
* Sets the width and height of the gadget in pixels.
* This is an override of the parent CStdGadget::SetSize() function. It will call the same named
* method in the parent class to perform the sizing operation and will then recalculate the
* positions of the parts within the status bar gadget to reflect the new size.
*
* @date Tuesday 23-Jun-2015 06:47 am, Code HQ Ehinger Tor
* @param a_iWidth Width of the gadget in pixels
* @param a_iHeight Height of the gadget in pixels
*/
void CStdGadgetStatusBar::SetSize(TInt a_iWidth, TInt a_iHeight)
{
#if defined(WIN32) && !defined(QT_GUI_LIB)
TInt Index, Offset, ParentWidth, *PartsOffsets;
RECT Rect;
/* Call the parent method to perform the sizing operation */
CStdGadget::SetSize(a_iWidth, a_iHeight);
/* Allocate a tempoary array in which to calculate the pixel offsets of the parts */
if ((PartsOffsets = new TInt[m_iNumParts]) != NULL)
{
Offset = 0;
ParentWidth = m_poParentWindow->InnerWidth();
/* Convert the percentage offsets of the parts into pixel offsets */
for (Index = 0; Index < m_iNumParts; ++Index)
{
PartsOffsets[Index] = (int) (Offset + (m_piPartsOffsets[Index] / 100.0f * ParentWidth));
Offset = PartsOffsets[Index];
}
/* Subdivide the status bar into the requested number of parts at the requested positions */
if (SendMessage(m_poGadget, SB_SETPARTS, m_iNumParts, (LPARAM) PartsOffsets))
{
/* And determine the dimensions of the gadget and save them for l8r */
if (GetClientRect(m_poGadget, &Rect))
{
m_iWidth = (Rect.right - Rect.left);
m_iHeight = m_iMinHeight = (Rect.bottom - Rect.top);
}
}
delete [] PartsOffsets;
}
#else /* ! (defined(WIN32) && !defined(QT_GUI_LIB) */
(void) a_iWidth;
(void) a_iHeight;
#endif /* ! (defined(WIN32) && !defined(QT_GUI_LIB) */
}
/* Written: Saturday 30-Apr-2011 8:51 am */
/* @param a_iPart Index of part of the status bar to which to assign the text */
/* a_pccText Text to assign to the status bar part */
/* Sets the content of the specified subpart of the status bar to the text passed in. */
/* If the old content is the same as the new content then nothing will be done, to */
/* avoid flicker */
void CStdGadgetStatusBar::SetText(TInt a_iPart, const char *a_pccText)
{
ASSERTM((a_iPart < m_iNumParts), "CStdGadgetStatusBar::SetText() => Part # is out of range");
ASSERTM((m_ppcPartsText != NULL), "CStdGadgetStatusBar::SetText() => Gadget not initialised");
/* Don't do anything if the content hasn't changed */
if (strcmp(GetText(a_iPart), a_pccText) != 0)
{
/* Save our own copy of the text so we don't have to depend on the underlying operating */
/* system if we want to retrieve it later */
if ((m_ppcPartsText[a_iPart] = (char *) Utils::GetTempBuffer(m_ppcPartsText[a_iPart], (strlen(a_pccText) + 1), EFalse)) != NULL)
{
strcpy(m_ppcPartsText[a_iPart], a_pccText);
}
#ifdef __amigaos__
/* It's not well documented but it appears that while OS4 string gadgets can adapt to text lengths, OS3 needs */
/* to preallocate its buffer, specified by STRINGA_MaxChars, and this cannot be changed later. Removing and */
/* re-adding a string gadget with a longer buffer is not an option so we'll do a runtime check and simply not */
/* set the new string if it's too long */
size_t Length = (strlen(a_pccText) + 1);
ASSERTM((Length < MAX_CHARS), "CStdGadgetStatusBar::SetText() => String is too long");
if (Length < MAX_CHARS)
{
SetGadgetAttrs((struct Gadget *) m_poPartsGadgets[a_iPart], m_poParentWindow->m_poWindow,
NULL, STRINGA_TextVal, a_pccText, TAG_DONE);
}
#elif defined(QT_GUI_LIB)
m_poPartsGadgets[a_iPart]->setText(a_pccText);
#elif defined(WIN32)
DEBUGCHECK((SendMessage(m_poGadget, SB_SETTEXT, a_iPart, (LPARAM) a_pccText) != FALSE), "CStdGadgetStatusBar::SetText() => Unable to set status bar text");
#endif /* WIN32 */
}
}