1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                MENUITEM.CC                                */
4 /*                                                                           */
5 /* (C) 1993-96  Ullrich von Bassewitz                                        */
6 /*              Wacholderweg 14                                              */
7 /*              D-70597 Stuttgart                                            */
8 /* EMail:       uz@ibb.schwaben.com                                          */
9 /*                                                                           */
10 /*****************************************************************************/
11 
12 
13 
14 // $Id$
15 //
16 // $Log$
17 //
18 //
19 
20 
21 
22 #include "menuitem.h"
23 #include "winattr.h"
24 #include "menuedit.h"
25 #include "progutil.h"
26 #include "streamid.h"
27 #include "strcvt.h"
28 #include "msgid.h"
29 
30 
31 
32 // Register the classes
33 LINK (MenueLine, ID_MenueLine);
34 LINK (LongItem, ID_LongItem);
35 LINK (HexItem, ID_HexItem);
36 LINK (StringItem, ID_StringItem);
37 LINK (ToggleItem, ID_ToggleItem);
38 LINK (OffOnItem, ID_OffOnItem);
39 LINK (NoYesItem, ID_NoYesItem);
40 LINK (FloatItem, ID_FloatItem);
41 LINK (TimeItem, ID_TimeItem);
42 LINK (DateItem, ID_DateItem);
43 LINK (RStringItem, ID_RStringItem);
44 
45 
46 
47 /*****************************************************************************/
48 /*                             Message constants                             */
49 /*****************************************************************************/
50 
51 
52 
53 static const u16 msOffOn                = MSGBASE_MENUITEM + 0;
54 static const u16 msNoYes                = MSGBASE_MENUITEM + 1;
55 
56 
57 
58 /*****************************************************************************/
59 /*                              class MenueLine                              */
60 /*****************************************************************************/
61 
62 
63 
MenueLine(i16 aID,WindowItem * NextItem)64 MenueLine::MenueLine (i16 aID, WindowItem *NextItem) :
65         MenueItem ("", aID, NextItem)
66 {
67     // Menuelines are inactive objects
68     Flags |= ifInactive;
69 }
70 
71 
72 
StreamableID() const73 u16 MenueLine::StreamableID () const
74 {
75     return ID_MenueLine;
76 }
77 
78 
79 
Build()80 Streamable* MenueLine::Build ()
81 {
82     return new MenueLine (Empty);
83 }
84 
85 
86 
BuildEntry(const String &)87 void MenueLine::BuildEntry (const String&)
88 // Rebuild Entry when the length has changed. The given String is
89 // ignored.
90 {
91     // Cut the entry string if it is longer than the new width
92     Entry.Trunc (ItemWidth);
93 
94     // Construct a new display string
95     Entry.Set (0, ItemWidth, InactiveFrame [fcHorizontal]);
96 
97     // Optimize memory
98     Entry.Settle ();
99 }
100 
101 
102 
MinWidth()103 u16 MenueLine::MinWidth ()
104 {
105     // A line has min width zero
106     return 0;
107 }
108 
109 
110 
111 /*****************************************************************************/
112 /*                            class EditMenueItem                            */
113 /*****************************************************************************/
114 
115 
116 
EditMenueItem(const String & aItemText,i16 aID,i16 EditID,ItemWindow * EditWin,WindowItem * NextItem)117 EditMenueItem::EditMenueItem (const String& aItemText, i16 aID, i16 EditID,
118                               ItemWindow* EditWin, WindowItem* NextItem) :
119         MenueItem (aItemText, aID, NextItem),
120         EditWindow (EditWin), EditItemID (EditID)
121 {
122 }
123 
124 
125 
~EditMenueItem()126 EditMenueItem::~EditMenueItem ()
127 {
128     delete EditWindow;
129 }
130 
131 
132 
Store(Stream & S) const133 void EditMenueItem::Store (Stream &S) const
134 // Store the object data into a stream
135 {
136     // Store parental data
137     MenueItem::Store (S);
138 
139     // Store instance data
140     S << EditItemID;
141     S.Put (EditWindow);
142 }
143 
144 
145 
Load(Stream & S)146 void EditMenueItem::Load (Stream &S)
147 // Load the object data from a stream
148 {
149     // Load parental data
150     MenueItem::Load (S);
151 
152     // Load instance data
153     S >> EditItemID;
154     EditWindow = (ItemWindow *) S.Get ();
155 }
156 
157 
158 
PlaceEditWindow()159 void EditMenueItem::PlaceEditWindow ()
160 // Place the edit window below this entry if EditWindow has no position
161 // (== has position 0/0).
162 {
163     if (EditWindow) {
164 
165         // Get the coords of the edit window
166         Rect Bounds (EditWindow->OuterBounds ());
167 
168         if (Bounds.A == Point (0, 0)) {
169 
170             // The edit window has no position. Get the coords of the
171             // item and make them absolute
172             Point P (ItemX, ItemY);
173             Owner->Absolute (P);
174 
175             // Now place the edit window below the entry
176             P.Y++;
177             EditWindow->MoveRel (P);
178         }
179     }
180 }
181 
182 
183 
ItemWithID(i16 aID)184 WindowItem* EditMenueItem::ItemWithID (i16 aID)
185 // Search for the item with the given ID. The editwindow (if one exists)
186 // is also searched.
187 {
188     if (ID == aID) {
189         return this;
190     } else {
191         return EditWindow ? EditWindow->ItemWithID (aID) : (WindowItem*) NULL;
192     }
193 }
194 
195 
196 
SetEditWindow(ItemWindow * Win,i16 EditID)197 void EditMenueItem::SetEditWindow (ItemWindow *Win, i16 EditID)
198 // Set the edit window. Beware: An already existing edit window is not
199 // deleted!
200 {
201     // Check the given parameters
202     PRECONDITION (Win == NULL || EditID != 0);
203 
204     // Store them
205     EditWindow = Win;
206     EditItemID = EditID;
207 }
208 
209 
210 
211 /*****************************************************************************/
212 /*                              class LongItem                               */
213 /*****************************************************************************/
214 
215 
216 
LongItem(const String & aItemText,i16 aID,u16 aDigits,i16 EditID,i32 Min,i32 Max,WindowItem * NextItem)217 LongItem::LongItem (const String& aItemText, i16 aID, u16 aDigits, i16 EditID,
218                     i32 Min, i32 Max, WindowItem* NextItem) :
219     EditMenueItem (aItemText, aID, EditID, NULL, NextItem),
220     LValue (Min),
221     Digits (aDigits),
222     LMin (Min),
223     LMax (Max)
224 {
225 }
226 
227 
228 
LongItem(const String & aItemText,i16 aID,u16 aDigits,WindowItem * NextItem)229 LongItem::LongItem (const String& aItemText, i16 aID, u16 aDigits,
230                     WindowItem* NextItem) :
231     EditMenueItem (aItemText, aID, 0, NULL, NextItem),
232     LValue (0),
233     Digits (aDigits),
234     LMin (0x80000000),
235     LMax (0x7FFFFFFF)
236 {
237 }
238 
239 
240 
Load(Stream & S)241 void LongItem::Load (Stream &S)
242 // Load the object data from a stream
243 {
244     // Load parental data
245     EditMenueItem::Load (S);
246 
247     // Load instance data
248     S >> LValue >> Digits >> LMin >> LMax;
249 }
250 
251 
252 
Store(Stream & S) const253 void LongItem::Store (Stream &S) const
254 // Store the object data into a stream
255 {
256     // Store parental data
257     EditMenueItem::Store (S);
258 
259     // Store instance data
260     S << LValue << Digits << LMin << LMax;
261 }
262 
263 
264 
StreamableID() const265 u16 LongItem::StreamableID () const
266 {
267     return ID_LongItem;
268 }
269 
270 
271 
Build()272 Streamable* LongItem::Build ()
273 {
274     return new LongItem (Empty);
275 }
276 
277 
278 
SetWidth(u16 NewWidth)279 void LongItem::SetWidth (u16 NewWidth)
280 {
281     // Check against the minimum width needed
282     if (NewWidth < MinWidth ()) {
283         // Ignore the request
284         return;
285     }
286 
287     // Store the new width
288     ItemWidth = NewWidth;
289 
290     // Convert the number to string
291     String S (I32Str (LValue));
292     S.ForceLen (Digits, String::Left);
293     S.Ins (0, ' ');
294     BuildEntry (S);
295 }
296 
297 
298 
MinWidth()299 u16 LongItem::MinWidth ()
300 {
301     u16 Len = ItemText.Len ();
302     u16 Width = Len + Digits + 2;       // One space to the left and right
303     if (Len) {
304         Width += 2;                     // Space between text and number
305     }
306     return Width;
307 }
308 
309 
310 
Choose()311 i16 LongItem::Choose ()
312 // Choose the entry. If an edit window is defined (EditWindow != NULL),
313 // the entry with id EditItemID in EditWindow is called. If there was
314 // no abort (or EditWindow is not defined), the id of this item is
315 // returned.
316 {
317     LongEdit *P;
318     int Abort;
319     i16 Result;
320 
321     // If the edit id is zero, return the own id
322     if (EditItemID == 0) {
323         return ID;
324     }
325 
326     // Check if a predefined window exists
327     if (EditWindow) {
328 
329         // Move the window to the correct position
330         PlaceEditWindow ();
331 
332         // Allow editing the value
333         P = (LongEdit *) EditWindow->ForcedItemWithID (EditItemID);
334         P->SetValue (LValue);
335         P->Edit (Abort);
336 
337         // if no abort, set the value and return the id
338         if (Abort) {
339             Result = 0;
340         } else {
341             SetValue (P->GetValue ());
342             Result = ID;
343         }
344 
345     } else {
346 
347         // No item defined, we have to create one
348         P = new LongEdit ("", EditItemID, Digits, NULL);
349 
350         // Insert the item into the owner window
351         Owner->AddItem (P);
352 
353         // Set the position of the newly created item
354         P->SetPos (ItemX + ItemWidth - P->GetWidth (), ItemY);
355 
356         // Deselect "this"
357         Deselect ();
358 
359         // Transfer the values from "this" to the new item. Calling
360         // SetValue will also draw the edit item
361         P->SetMinMax (LMin, LMax);
362         P->SetValue (LValue);
363 
364         // allow editing
365         P->Edit (Abort);
366 
367         // Get the edited value if the editing was not aborted
368         if (Abort) {
369             Result = 0;
370         } else {
371             SetValue (P->GetValue ());
372             Result = ID;
373         }
374 
375         // Delete the edit item from the owners list
376         Owner->DeleteItem (P);
377 
378         // Select "this". This redraws the item and clears the edit field
379         Select ();
380 
381     }
382 
383     // Return the result
384     return Result;
385 
386 }
387 
388 
389 
SetValue(i32 Val)390 void LongItem::SetValue (i32 Val)
391 {
392     // Store the new value
393     LValue = Val;
394 
395     // Build the new display text. As the number of digits is fixed,
396     // the length cannot change.
397     // Use SetWidth with the current width to do that
398     SetWidth (ItemWidth);
399 
400     // Now redraw the item
401     Draw ();
402 }
403 
404 
405 
SetMinMax(i32 Min,i32 Max)406 void LongItem::SetMinMax (i32 Min, i32 Max)
407 {
408     // Check parameters
409     PRECONDITION (Min <= Max);
410 
411     LMin = Min;
412     LMax = Max;
413 }
414 
415 
416 
417 /*****************************************************************************/
418 /*                               class HexItem                               */
419 /*****************************************************************************/
420 
421 
422 
StreamableID() const423 u16 HexItem::StreamableID () const
424 {
425     return ID_LongItem;
426 }
427 
428 
429 
Build()430 Streamable* HexItem::Build ()
431 {
432     return new HexItem (Empty);
433 }
434 
435 
436 
SetWidth(u16 NewWidth)437 void HexItem::SetWidth (u16 NewWidth)
438 {
439     // Check against the minimum width needed
440     if (NewWidth < MinWidth ()) {
441         // Ignore the request
442         return;
443     }
444 
445     // Store the new width
446     ItemWidth = NewWidth;
447 
448     // Convert the number to string
449     String S (U32Str (LValue, 16));
450     S.ForceLen (Digits, String::Left);
451     S.Ins (0, ' ');
452     BuildEntry (S);
453 }
454 
455 
456 
Choose()457 i16 HexItem::Choose ()
458 // Choose the entry. If an edit window is defined (EditWindow != NULL),
459 // the entry with id EditItemID in EditWindow is called. If there was
460 // no abort (or EditWindow is not defined), the id of this item is
461 // returned.
462 {
463     HexEdit *P;
464     int Abort;
465     i16 Result;
466 
467     // If the edit id is zero, return the own id
468     if (EditItemID == 0) {
469         return ID;
470     }
471 
472     // Check if a predefined window exists
473     if (EditWindow) {
474 
475         // Move the window to the correct position
476         PlaceEditWindow ();
477 
478         // Allow editing the value
479         P = (HexEdit *) EditWindow->ForcedItemWithID (EditItemID);
480         P->SetValue (LValue);
481         P->Edit (Abort);
482 
483         // if no abort, set the value and return the id
484         if (Abort) {
485             Result = 0;
486         } else {
487             SetValue (P->GetValue ());
488             Result = ID;
489         }
490 
491     } else {
492 
493         // No item defined, we have to create one
494         P = new HexEdit ("", EditItemID, Digits, NULL);
495 
496         // Insert the item into the owner window
497         Owner->AddItem (P);
498 
499         // Set the position of the newly created item
500         P->SetPos (ItemX + ItemWidth - P->GetWidth (), ItemY);
501 
502         // Deselect "this"
503         Deselect ();
504 
505         // Transfer the values from "this" to the new item. Calling
506         // SetValue will also draw the edit item
507         P->SetMinMax (LMin, LMax);
508         P->SetValue (LValue);
509 
510         // allow editing
511         P->Edit (Abort);
512 
513         // Get the edited value if the editing was not aborted
514         if (Abort) {
515             Result = 0;
516         } else {
517             SetValue (P->GetValue ());
518             Result = ID;
519         }
520 
521         // Delete the edit item from the owners list
522         Owner->DeleteItem (P);
523 
524         // Select "this". This redraws the item and clears the edit field
525         Select ();
526 
527     }
528 
529     // Return the result
530     return Result;
531 
532 }
533 
534 
535 
536 /*****************************************************************************/
537 /*                             class StringItem                              */
538 /*****************************************************************************/
539 
540 
541 
StringItem(const String & aItemText,i16 aID,i16 EditID,WindowItem * NextItem)542 StringItem::StringItem (const String& aItemText, i16 aID, i16 EditID,
543                         WindowItem* NextItem) :
544     EditMenueItem (aItemText, aID, EditID, NULL, NextItem)
545 {
546     // Allow all input chars
547     AllowedChars.SetAll ();
548 }
549 
550 
551 
StringItem(StreamableInit)552 StringItem::StringItem (StreamableInit) :
553     EditMenueItem (Empty),
554     SValue (Empty)
555 {
556     // Allow all chars
557     AllowedChars.SetAll ();
558 }
559 
560 
561 
Load(Stream & S)562 void StringItem::Load (Stream &S)
563 // Load the object data from a stream
564 {
565     // Load parental data
566     EditMenueItem::Load (S);
567 
568     // Load instance data
569     S >> SValue;
570 }
571 
572 
573 
Store(Stream & S) const574 void StringItem::Store (Stream &S) const
575 // Store the object data into a stream
576 {
577     // Store parental data
578     EditMenueItem::Store (S);
579 
580     // Store instance data
581     S << SValue;
582 }
583 
584 
585 
StreamableID() const586 u16 StringItem::StreamableID () const
587 {
588     return ID_StringItem;
589 }
590 
591 
592 
Build()593 Streamable* StringItem::Build ()
594 {
595     return new StringItem (Empty);
596 }
597 
598 
599 
SetWidth(u16 NewWidth)600 void StringItem::SetWidth (u16 NewWidth)
601 {
602     // Check against the minimum width needed
603     u16 MinW = MinWidth ();
604     if (NewWidth < MinW) {
605         // Ignore the request
606         return;
607     }
608 
609     // Store the new width
610     ItemWidth = NewWidth;
611 
612     // Get a copy of the value string, pad it left to the length needed
613     String S (SValue);
614     S.Pad (String::Left, ItemWidth - MinW);
615 
616     // Build the new entry
617     S.Ins (0, ' ');
618     BuildEntry (S);
619 }
620 
621 
622 
MinWidth()623 u16 StringItem::MinWidth ()
624 {
625     u16 Len = ItemText.Len ();
626     u16 Width = Len + 2;        // One space to the left and right
627     if (Len > 0) {
628         Width += 2;             // Add two spaces between text and string
629     }
630     return Width;
631 }
632 
633 
634 
Choose()635 i16 StringItem::Choose ()
636 // Choose the entry. If an edit window is defined (EditWindow != NULL),
637 // the entry with id EditItemID in EditWindow is called. If there was
638 // no abort (or EditWindow is not defined), the id of this item is
639 // returned.
640 {
641     int Abort;
642     i16 Result;
643 
644     // If the edit id is zero, return the own id
645     if (EditItemID == 0) {
646         return ID;
647     }
648 
649     // Check if a predefined window exists
650     if (EditWindow) {
651 
652         // Move the window to the correct position
653         PlaceEditWindow ();
654 
655         // Allow editing the value
656         TextEdit* P = (TextEdit*) EditWindow->ForcedItemWithID (EditItemID);
657         P->SetValue (SValue);
658         P->Edit (Abort);
659 
660         // if no abort, set the value and return the id
661         if (Abort) {
662             Result = 0;
663         } else {
664             SetValue (P->GetValue ());
665             Result = ID;
666         }
667 
668     } else {
669 
670         // No item defined, we have to create one
671         u16 Len = ItemWidth - MinWidth () - 1;
672         TextEdit* P = new TextEdit ("", EditItemID, Len-1, Len, NULL);
673 
674         // Set the allowed characters for input
675         P->SetAllowedChars (AllowedChars);
676 
677         // Insert the item into the owner window
678         Owner->AddItem (P);
679 
680         // Set the position of the newly created item
681         P->SetPos (ItemX + ItemWidth - P->GetWidth (), ItemY);
682 
683         // Deselect "this"
684         Deselect ();
685 
686         // Transfer the values from "this" to the new item. Calling
687         // SetValue will also draw the edit item
688         P->SetValue (SValue);
689 
690         // allow editing
691         P->Edit (Abort);
692 
693         // Get the edited value if the editing was not aborted
694         if (Abort) {
695             Result = 0;
696         } else {
697             SetValue (P->GetValue ());
698             Result = ID;
699         }
700 
701         // Delete the edit item from the owners list
702         Owner->DeleteItem (P);
703 
704         // Select "this". This redraws the item and clears the edit field
705         Select ();
706 
707     }
708 
709     // Return the result
710     return Result;
711 
712 }
713 
714 
715 
SetValue(const String & NewVal)716 void StringItem::SetValue (const String& NewVal)
717 {
718     // Store the new value
719     SValue = NewVal;
720     SValue.Settle ();
721 
722     // Build the new display text. As the number of digits is fixed,
723     // the length cannot change.
724     // Use SetWidth with the current width to do that
725     SetWidth (ItemWidth);
726 
727     // Now redraw the item
728     Draw ();
729 }
730 
731 
732 
GetAllowedChars() const733 const CharSet& StringItem::GetAllowedChars () const
734 // Get the set of allowed input chars
735 {
736     return AllowedChars;
737 }
738 
739 
740 
SetAllowedChars(const CharSet & CS)741 void StringItem::SetAllowedChars (const CharSet& CS)
742 // Set the allowed input chars
743 {
744     AllowedChars = CS;
745 }
746 
747 
748 
AllowEmptyInput()749 void StringItem::AllowEmptyInput ()
750 // Allow an empty input
751 {
752     AllowedChars += '\0';
753 }
754 
755 
756 
DisallowEmptyInput()757 void StringItem::DisallowEmptyInput ()
758 // Disallow an empty input line
759 {
760     AllowedChars -= '\0';
761 }
762 
763 
764 
765 /*****************************************************************************/
766 /*                             class ToggleItem                              */
767 /*****************************************************************************/
768 
769 
770 
ToggleItem(const String & aItemText,i16 aID,const String & ToggleList,unsigned ToggleCount,WindowItem * NextItem)771 ToggleItem::ToggleItem (const String& aItemText, i16 aID,
772                         const String& ToggleList, unsigned ToggleCount,
773                         WindowItem* NextItem) :
774     StringItem (aItemText, aID, 0, NextItem),
775     TValue (0),
776     TCount (ToggleCount),
777     TList (ToggleList)
778 {
779     // Get the length of the value list
780     u16 Len = TList.Len ();
781 
782     // Check the parameters
783     PRECONDITION (Len != 0 && TCount != 0 && (Len % TCount) == 0);
784 
785     // Initialize variables
786     ItemWidth = MinWidth ();
787     TLen = Len / TCount;
788     SValue = TList.Cut (0, TLen);
789 }
790 
791 
792 
Load(Stream & S)793 void ToggleItem::Load (Stream& S)
794 // Load an object from a stream
795 {
796     // Load parental data
797     StringItem::Load (S);
798 
799     // Load new data
800     S >> TValue >> TCount >> TLen >> TList;
801 }
802 
803 
804 
Store(Stream & S) const805 void ToggleItem::Store (Stream& S) const
806 // Store an object into a stream
807 {
808     // Store parental data
809     StringItem::Store (S);
810 
811     // Store new data
812     S << TValue << TCount << TLen << TList;
813 }
814 
815 
816 
StreamableID() const817 u16 ToggleItem::StreamableID () const
818 {
819     return ID_ToggleItem;
820 }
821 
822 
823 
Build()824 Streamable* ToggleItem::Build ()
825 {
826     return new ToggleItem (Empty);
827 }
828 
829 
830 
SetValue(u16 NewVal)831 void ToggleItem::SetValue (u16 NewVal)
832 // Set the new value of the toggle item
833 {
834     // Check the new value
835     PRECONDITION (NewVal < TCount);
836 
837     // Remember the new value
838     TValue = NewVal;
839 
840     // Use the inherited function to set the actual value
841     StringItem::SetValue (TList.Cut (TValue * TLen, TLen));
842 }
843 
844 
845 
Toggle()846 void ToggleItem::Toggle ()
847 // Toggle the value
848 {
849     // Select the next value
850     if (++TValue >= TCount) {
851         TValue = 0;
852     }
853     SetValue (TValue);
854 }
855 
856 
857 
SetWidth(u16 NewWidth)858 void ToggleItem::SetWidth (u16 NewWidth)
859 // Set the new entry width
860 {
861     // Check if the new width is acceptable
862     u16 WMin = MinWidth ();
863     if (NewWidth < WMin) {
864         // Ignore the request
865         return;
866     }
867 
868     // Remember the new value
869     ItemWidth = NewWidth;
870 
871     // Build the new entry
872     if (SValue.Len () == 0) {
873         BuildEntry (" ");
874     } else {
875         String S;
876         S.Set (0, ItemWidth - WMin);
877 
878         // One space between value and itemtext
879         if (ItemText.Len () != 0) {
880             S += ' ';
881         }
882 
883         BuildEntry (S + SValue);
884     }
885 
886 }
887 
888 
889 
MinWidth()890 u16 ToggleItem::MinWidth ()
891 // return the width needed
892 {
893     u16 Len = ItemText.Len ();
894     return Len ? Len + TLen + 4 : Len + TLen + 2;
895 }
896 
897 
898 
ItemWithID(i16 aID)899 WindowItem * ToggleItem::ItemWithID (i16 aID)
900 // Return a pointer to this if the given ID is the ID of the object.
901 // A ToggleItem uses all IDs from ID to ID + ToggleCount - 1
902 {
903     if (aID >= ID && aID < (ID + TCount)) {
904         return this;
905     } else {
906         return NULL;
907     }
908 }
909 
910 
911 
GetID()912 i16 ToggleItem::GetID ()
913 // Return the ID of the entry. The returned ID is the ID of the item plus
914 // the current toggle value
915 {
916     return ID + TValue;
917 }
918 
919 
920 
Choose()921 i16 ToggleItem::Choose ()
922 // Choose this entry. This implementation toggles to the next value and
923 // returns the corresponding ID
924 {
925     // No chance if the item is inactive
926     if (!IsActive ()) {
927         return 0;
928     }
929 
930     // Select and show the next toggle value
931     Toggle ();
932 
933     // Now return the ID
934     return GetID ();
935 }
936 
937 
938 
939 /*****************************************************************************/
940 /*                              class OffOnItem                              */
941 /*****************************************************************************/
942 
943 
944 
OffOnItem(const String & aItemText,i16 aID,WindowItem * NextItem)945 OffOnItem::OffOnItem (const String& aItemText, i16 aID, WindowItem* NextItem) :
946         ToggleItem (aItemText, aID, LoadMsg (msOffOn), 2, NextItem)
947 {
948 }
949 
950 
951 
StreamableID() const952 u16 OffOnItem::StreamableID () const
953 {
954     return ID_OffOnItem;
955 }
956 
957 
958 
Load(Stream & S)959 void OffOnItem::Load (Stream& S)
960 {
961     // Load data from ToggleItem
962     ToggleItem::Load (S);
963 
964     // Now override the toggle text (loading this instance in a new language
965     // environment should show the new language when loaded)
966     TList = LoadMsg (msOffOn);
967     TLen = TList.Len () / 2;
968     SValue = TList.Cut (TValue * TLen, TLen);
969 }
970 
971 
972 
Build()973 Streamable* OffOnItem::Build ()
974 {
975     return new OffOnItem (Empty);
976 }
977 
978 
979 
980 /*****************************************************************************/
981 /*                              class NoYesItem                              */
982 /*****************************************************************************/
983 
984 
985 
NoYesItem(const String & aItemText,i16 aID,WindowItem * NextItem)986 NoYesItem::NoYesItem (const String& aItemText, i16 aID, WindowItem* NextItem) :
987     ToggleItem (aItemText, aID, LoadMsg (msNoYes), 2, NextItem)
988 {
989 }
990 
991 
992 
StreamableID() const993 u16 NoYesItem::StreamableID () const
994 {
995     return ID_NoYesItem;
996 }
997 
998 
999 
Load(Stream & S)1000 void NoYesItem::Load (Stream& S)
1001 {
1002     // Load data from ToggleItem
1003     ToggleItem::Load (S);
1004 
1005     // Now override the toggle text (loading this instance in a new language
1006     // environment should show the new language when loaded)
1007     TList = LoadMsg (msNoYes);
1008     TLen = TList.Len () / 2;
1009     SValue = TList.Cut (TValue * TLen, TLen);
1010 }
1011 
1012 
1013 
Build()1014 Streamable* NoYesItem::Build ()
1015 {
1016     return new NoYesItem (Empty);
1017 }
1018 
1019 
1020 
1021 /*****************************************************************************/
1022 /*                              class FloatItem                              */
1023 /*****************************************************************************/
1024 
1025 
1026 
FloatItem(const String & aItemText,i16 aID,u16 aLD,u16 aTD,u16 EditID,double Min,double Max,WindowItem * NextItem)1027 FloatItem::FloatItem (const String& aItemText, i16 aID, u16 aLD, u16 aTD,
1028                       u16 EditID, double Min, double Max, WindowItem* NextItem) :
1029     EditMenueItem (aItemText, aID, EditID, NULL, NextItem),
1030     FValue (Min),
1031     LD (aLD),
1032     TD (aTD),
1033     FMin (Min),
1034     FMax (Max)
1035 {
1036 }
1037 
1038 
1039 
FloatItem(const String & aItemText,i16 aID,u16 aLD,u16 aTD,WindowItem * NextItem)1040 FloatItem::FloatItem (const String& aItemText, i16 aID, u16 aLD, u16 aTD,
1041                       WindowItem* NextItem) :
1042     EditMenueItem (aItemText, aID, 0, NULL, NextItem),
1043     FValue (0),
1044     LD (aLD),
1045     TD (aTD),
1046     FMin (-100000),
1047     FMax (+100000)
1048 {
1049 }
1050 
1051 
1052 
Load(Stream & S)1053 void FloatItem::Load (Stream &S)
1054 // Load the instance from a stream
1055 {
1056     EditMenueItem::Load (S);
1057     S >> FValue >> LD >> TD >> FMin >> FMax;
1058 }
1059 
1060 
1061 
Store(Stream & S) const1062 void FloatItem::Store (Stream &S) const
1063 // Store the instance into a stream
1064 {
1065     EditMenueItem::Store (S);
1066     S << FValue << LD << TD << FMin << FMax;
1067 }
1068 
1069 
1070 
StreamableID() const1071 u16 FloatItem::StreamableID () const
1072 {
1073     return ID_FloatItem;
1074 }
1075 
1076 
1077 
Build()1078 Streamable* FloatItem::Build ()
1079 {
1080     return new FloatItem (Empty);
1081 }
1082 
1083 
1084 
SetValue(double Val)1085 void FloatItem::SetValue (double Val)
1086 // Set the new value of the float item
1087 {
1088     // Store the new value
1089     FValue = Val;
1090 
1091     // Build the new display text. As the number of digits is fixed,
1092     // the length cannot change.
1093     // Use SetWidth with the current width to do that
1094     SetWidth (ItemWidth);
1095 
1096     // Now redraw the item
1097     Draw ();
1098 }
1099 
1100 
1101 
SetMinMax(double Min,double Max)1102 void FloatItem::SetMinMax (double Min, double Max)
1103 // Set the values for FMin/FMax
1104 {
1105     FMin = Min;
1106     FMax = Max;
1107 }
1108 
1109 
1110 
SetWidth(u16 NewWidth)1111 void FloatItem::SetWidth (u16 NewWidth)
1112 // Set the new entry width
1113 {
1114     // Check against the minimum width needed
1115     if (NewWidth < MinWidth ()) {
1116         // Ignore the request
1117         return;
1118     }
1119 
1120     // Store the new width
1121     ItemWidth = NewWidth;
1122 
1123     // Build the new entry
1124     String S (FloatStr (FValue, LD, TD));
1125     S.ForceLen (TD ? LD + TD + 1 : LD, String::Left);
1126     BuildEntry (S);
1127 }
1128 
1129 
1130 
MinWidth()1131 u16 FloatItem::MinWidth ()
1132 // return the width needed
1133 {
1134     u16 Len = ItemText.Len ();
1135     u16 Width = Len + 2 + LD + TD;              // one space left and right
1136     if (TD > 0) {
1137         Width++;                                // Decimal point
1138     }
1139     if (Len > 0) {
1140         Width += 2;                             // Space between float and text
1141     }
1142     return Width;
1143 }
1144 
1145 
1146 
Choose()1147 i16 FloatItem::Choose ()
1148 // Choose the entry. If an edit window is defined (EditWindow != NULL),
1149 // the entry with id EditItemID in EditWindow is called. If there was
1150 // no abort (or EditWindow is not defined), the id of this item is
1151 // returned.
1152 {
1153     FloatEdit *P;
1154     int Abort;
1155     i16 Result;
1156 
1157     // If the edit id is zero, return the own id
1158     if (EditItemID == 0) {
1159         return ID;
1160     }
1161 
1162     // Check if a predefined window exists
1163     if (EditWindow) {
1164 
1165         // Move the window to the correct position
1166         PlaceEditWindow ();
1167 
1168         // Allow editing the value
1169         P = (FloatEdit *) EditWindow->ForcedItemWithID (EditItemID);
1170         P->SetValue (FValue);
1171         P->Edit (Abort);
1172 
1173         // if no abort, set the value and return the id
1174         if (Abort) {
1175             Result = 0;
1176         } else {
1177             SetValue (P->GetValue ());
1178             Result = ID;
1179         }
1180 
1181     } else {
1182 
1183         // No item defined, we have to create one
1184         P = new FloatEdit ("", EditItemID, LD, TD, NULL);
1185 
1186         // Insert the item into the owner window
1187         Owner->AddItem (P);
1188 
1189         // Set the position of the newly created item
1190         P->SetPos (ItemX + ItemWidth - P->GetWidth (), ItemY);
1191 
1192         // Deselect "this"
1193         Deselect ();
1194 
1195         // Transfer the values from "this" to the new item. Calling
1196         // SetValue will also draw the edit item
1197         P->SetMinMax (FMin, FMax);
1198         P->SetValue (FValue);
1199 
1200         // allow editing
1201         P->Edit (Abort);
1202 
1203         // Get the edited value if the editing was not aborted
1204         if (Abort) {
1205             Result = 0;
1206         } else {
1207             SetValue (P->GetValue ());
1208             Result = ID;
1209         }
1210 
1211         // Delete the edit item from the owners list
1212         Owner->DeleteItem (P);
1213 
1214         // Select "this". This redraws the item and clears the edit field
1215         Select ();
1216 
1217     }
1218 
1219     // Return the result
1220     return Result;
1221 
1222 }
1223 
1224 
1225 
1226 /*****************************************************************************/
1227 /*                              class TimeItem                               */
1228 /*****************************************************************************/
1229 
1230 
1231 
TimeItem(const String & aItemText,i16 aID,i16 EditID,WindowItem * NextItem)1232 TimeItem::TimeItem (const String& aItemText, i16 aID, i16 EditID,
1233                     WindowItem* NextItem) :
1234     EditMenueItem (aItemText, aID, EditID, NULL, NextItem)
1235 {
1236 }
1237 
1238 
1239 
TimeItem(const String & aItemText,i16 aID,WindowItem * NextItem)1240 TimeItem::TimeItem (const String& aItemText, i16 aID, WindowItem* NextItem) :
1241     EditMenueItem (aItemText, aID, 0, NULL, NextItem)
1242 {
1243 }
1244 
1245 
1246 
Load(Stream & S)1247 void TimeItem::Load (Stream &S)
1248 {
1249     EditMenueItem::Load (S);
1250     S >> TimeVal;
1251 }
1252 
1253 
1254 
Store(Stream & S) const1255 void TimeItem::Store (Stream &S) const
1256 {
1257     EditMenueItem::Store (S);
1258     S << TimeVal;
1259 }
1260 
1261 
1262 
StreamableID() const1263 u16 TimeItem::StreamableID () const
1264 {
1265     return ID_TimeItem;
1266 }
1267 
1268 
1269 
Build()1270 Streamable* TimeItem::Build ()
1271 {
1272     return new TimeItem (Empty);
1273 }
1274 
1275 
1276 
SetWidth(u16 NewWidth)1277 void TimeItem::SetWidth (u16 NewWidth)
1278 {
1279     // Check against the minimum width needed
1280     if (NewWidth < MinWidth ()) {
1281         // Ignore the request
1282         return;
1283     }
1284 
1285     // Store the new width
1286     ItemWidth = NewWidth;
1287 
1288     // Build the new entry
1289     BuildEntry (TimeVal.TimeStr ());
1290 }
1291 
1292 
1293 
MinWidth()1294 u16 TimeItem::MinWidth ()
1295 {
1296     u16 Len = ItemText.Len ();
1297     u16 Width = Len + TimeVal.TimeStr().Len() + 2;
1298     if (Len) {
1299         Width += 2;
1300     }
1301     return Width;
1302 }
1303 
1304 
1305 
Choose()1306 i16 TimeItem::Choose ()
1307 // Choose the entry. If an edit window is defined (EditWindow != NULL),
1308 // the entry with id EditItemID in EditWindow is called. If there was
1309 // no abort (or EditWindow is not defined), the id of this item is
1310 // returned.
1311 {
1312     TimeEdit *P;
1313     int Abort;
1314     i16 Result;
1315 
1316     // If the edit id is zero, return the own id
1317     if (EditItemID == 0) {
1318         return ID;
1319     }
1320 
1321     // Check if a predefined window exists
1322     if (EditWindow) {
1323 
1324         // Move the window to the correct position
1325         PlaceEditWindow ();
1326 
1327         // Allow editing the value
1328         P = (TimeEdit *) EditWindow->ForcedItemWithID (EditItemID);
1329         P->SetValue (TimeVal);
1330         P->Edit (Abort);
1331 
1332         // if no abort, set the value and return the id
1333         if (Abort) {
1334             Result = 0;
1335         } else {
1336             SetValue (P->GetValue ());
1337             Result = ID;
1338         }
1339 
1340     } else {
1341 
1342         // No item defined, we have to create one
1343         P = new TimeEdit ("", EditItemID, NULL);
1344 
1345         // Insert the item into the owner window
1346         Owner->AddItem (P);
1347 
1348         // Set the position of the newly created item
1349         P->SetPos (ItemX + ItemWidth - P->GetWidth (), ItemY);
1350 
1351         // Deselect "this"
1352         Deselect ();
1353 
1354         // Transfer the values from "this" to the new item. Calling
1355         // SetValue will also draw the edit item
1356         P->SetValue (TimeVal);
1357 
1358         // allow editing
1359         P->Edit (Abort);
1360 
1361         // Get the edited value if the editing was not aborted
1362         if (Abort) {
1363             Result = 0;
1364         } else {
1365             SetValue (P->GetValue ());
1366             Result = ID;
1367         }
1368 
1369         // Delete the edit item from the owners list
1370         Owner->DeleteItem (P);
1371 
1372         // Select "this". This redraws the item and clears the edit field
1373         Select ();
1374 
1375     }
1376 
1377     // Return the result
1378     return Result;
1379 
1380 }
1381 
1382 
1383 
SetValue(unsigned Hour,unsigned Minute,unsigned Second)1384 void TimeItem::SetValue (unsigned Hour, unsigned Minute, unsigned Second)
1385 {
1386     // Set the new value
1387     TimeVal.SetTime (Hour, Minute, Second);
1388 
1389     // Build the new display text.
1390     // Use SetWidth with the current width to do that
1391     SetWidth (ItemWidth);
1392 
1393     // Now redraw the item
1394     Draw ();
1395 }
1396 
1397 
1398 
SetValue(u32 Seconds)1399 void TimeItem::SetValue (u32 Seconds)
1400 {
1401     unsigned Sec  = Seconds % 60;
1402     Seconds /= 60;
1403     unsigned Min  = Seconds % 60;
1404     unsigned Hour = Seconds / 60;
1405     CHECK (Hour < 24);
1406 
1407     // Set the new value
1408     SetValue (Hour, Min, Sec);
1409 }
1410 
1411 
1412 
SetValue(const Time & Val)1413 void TimeItem::SetValue (const Time& Val)
1414 {
1415     // Set the new value
1416     TimeVal = Val;
1417 
1418     // Build the new display text.
1419     // Use SetWidth with the current width to do that
1420     SetWidth (ItemWidth);
1421 
1422     // Now redraw the item
1423     Draw ();
1424 }
1425 
1426 
1427 
1428 /*****************************************************************************/
1429 /*                              class DateItem                               */
1430 /*****************************************************************************/
1431 
1432 
1433 
1434 
DateItem(const String & aItemText,i16 aID,i16 EditID,WindowItem * NextItem)1435 DateItem::DateItem (const String& aItemText, i16 aID, i16 EditID,
1436                            WindowItem* NextItem) :
1437     EditMenueItem (aItemText, aID, EditID, NULL, NextItem)
1438 {
1439 }
1440 
1441 
1442 
DateItem(const String & aItemText,i16 aID,WindowItem * NextItem)1443 DateItem::DateItem (const String& aItemText, i16 aID, WindowItem* NextItem) :
1444     EditMenueItem (aItemText, aID, 0, NULL, NextItem)
1445 {
1446 }
1447 
1448 
1449 
Load(Stream & S)1450 void DateItem::Load (Stream &S)
1451 {
1452     EditMenueItem::Load (S);
1453     S >> TimeVal;
1454 }
1455 
1456 
1457 
Store(Stream & S) const1458 void DateItem::Store (Stream &S) const
1459 {
1460     EditMenueItem::Store (S);
1461     S << TimeVal;
1462 }
1463 
1464 
1465 
StreamableID() const1466 u16 DateItem::StreamableID () const
1467 {
1468     return ID_DateItem;
1469 }
1470 
1471 
1472 
Build()1473 Streamable* DateItem::Build ()
1474 {
1475     return new DateItem (Empty);
1476 }
1477 
1478 
1479 
SetWidth(u16 NewWidth)1480 void DateItem::SetWidth (u16 NewWidth)
1481 {
1482     // Check against the minimum width needed
1483     if (NewWidth < MinWidth ()) {
1484         // Ignore the request
1485         return;
1486     }
1487 
1488     // Store the new width
1489     ItemWidth = NewWidth;
1490 
1491     // Build the new entry
1492     BuildEntry (TimeVal.DateStr ());
1493 }
1494 
1495 
1496 
MinWidth()1497 u16 DateItem::MinWidth ()
1498 {
1499     u16 Len = ItemText.Len ();
1500     u16 Width = Len + TimeVal.DateStr().Len() + 2;
1501     if (Len) {
1502         Width += 2;
1503     }
1504     return Width;
1505 }
1506 
1507 
1508 
Choose()1509 i16 DateItem::Choose ()
1510 // Choose the entry. If an edit window is defined (EditWindow != NULL),
1511 // the entry with id EditItemID in EditWindow is called. If there was
1512 // no abort (or EditWindow is not defined), the id of this item is
1513 // returned.
1514 {
1515     DateEdit *P;
1516     int Abort;
1517     i16 Result;
1518 
1519     // If the edit id is zero, return the own id
1520     if (EditItemID == 0) {
1521         return ID;
1522     }
1523 
1524     // Check if a predefined window exists
1525     if (EditWindow) {
1526 
1527         // Move the window to the correct position
1528         PlaceEditWindow ();
1529 
1530         // Allow editing the value
1531         P = (DateEdit *) EditWindow->ForcedItemWithID (EditItemID);
1532         P->SetValue (TimeVal);
1533         P->Edit (Abort);
1534 
1535         // if no abort, set the value and return the id
1536         if (Abort) {
1537             Result = 0;
1538         } else {
1539             SetValue (P->GetValue ());
1540             Result = ID;
1541         }
1542 
1543     } else {
1544 
1545         // No item defined, we have to create one
1546         P = new DateEdit ("", EditItemID, NULL);
1547 
1548         // Insert the item into the owner window
1549         Owner->AddItem (P);
1550 
1551         // Set the position of the newly created item
1552         P->SetPos (ItemX + ItemWidth - P->GetWidth (), ItemY);
1553 
1554         // Deselect "this"
1555         Deselect ();
1556 
1557         // Transfer the values from "this" to the new item. Calling
1558         // SetValue will also draw the edit item
1559         P->SetValue (TimeVal);
1560 
1561         // allow editing
1562         P->Edit (Abort);
1563 
1564         // Get the edited value if the editing was not aborted
1565         if (Abort) {
1566             Result = 0;
1567         } else {
1568             SetValue (P->GetValue ());
1569             Result = ID;
1570         }
1571 
1572         // Delete the edit item from the owners list
1573         Owner->DeleteItem (P);
1574 
1575         // Select "this". This redraws the item and clears the edit field
1576         Select ();
1577 
1578     }
1579 
1580     // Return the result
1581     return Result;
1582 
1583 }
1584 
1585 
1586 
SetValue(unsigned Year,unsigned Month,unsigned Day)1587 void DateItem::SetValue (unsigned Year, unsigned Month, unsigned Day)
1588 {
1589     // Set the new value
1590     TimeVal.SetDate (Year, Month, Day);
1591 
1592     // Build the new display text.
1593     // Use SetWidth with the current width to do that
1594     SetWidth (ItemWidth);
1595 
1596     // Now redraw the item
1597     Draw ();
1598 }
1599 
1600 
1601 
SetValue(const Time & Val)1602 void DateItem::SetValue (const Time& Val)
1603 {
1604     // Set the new value
1605     TimeVal = Val;
1606 
1607     // Build the new display text.
1608     // Use SetWidth with the current width to do that
1609     SetWidth (ItemWidth);
1610 
1611     // Now redraw the item
1612     Draw ();
1613 }
1614 
1615 
1616 
1617 /*****************************************************************************/
1618 /*                             class RStringItem                             */
1619 /*****************************************************************************/
1620 
1621 
1622 
1623 // Class RStringItem has the same functionality as class StringItem with one
1624 // exception: The set of allowed input characters is written out on a Store
1625 // and reloaded when calling Load. This has been a compatibility decision:
1626 // The complete functionality to restrict input has been added to class
1627 // StringItem (without changing the default behavior), but writing out the
1628 // additional class would have made existing resources unusable - so there
1629 // is a new class for that.
1630 
1631 
1632 
RStringItem(StreamableInit)1633 RStringItem::RStringItem (StreamableInit):
1634     StringItem (Empty)
1635 // Build constructor
1636 {
1637 }
1638 
1639 
1640 
RStringItem(const String & aItemText,i16 aID,i16 EditID,u16 aInputLength,WindowItem * NextItem)1641 RStringItem::RStringItem (const String& aItemText, i16 aID, i16 EditID,
1642                           u16 aInputLength, WindowItem* NextItem):
1643     StringItem (aItemText, aID, EditID, NextItem),
1644     InputLength (aInputLength)
1645 {
1646 }
1647 
1648 
1649 
Load(Stream & S)1650 void RStringItem::Load (Stream& S)
1651 {
1652     StringItem::Load (S);
1653     S >> AllowedChars >> InputLength;
1654 }
1655 
1656 
1657 
Store(Stream & S) const1658 void RStringItem::Store (Stream& S) const
1659 {
1660     StringItem::Store (S);
1661     S << AllowedChars << InputLength;
1662 }
1663 
1664 
1665 
StreamableID() const1666 u16 RStringItem::StreamableID () const
1667 {
1668     return ID_RStringItem;
1669 }
1670 
1671 
1672 
Build()1673 Streamable* RStringItem::Build ()
1674 {
1675     return new RStringItem (Empty);
1676 }
1677 
1678 
1679 
Choose()1680 i16 RStringItem::Choose ()
1681 // Choose the entry. If an edit window is defined (EditWindow != NULL),
1682 // the entry with id EditItemID in EditWindow is called. If there was
1683 // no abort (or EditWindow is not defined), the id of this item is
1684 // returned.
1685 {
1686     int Abort;
1687     i16 Result;
1688 
1689     // If the edit id is zero, return the own id
1690     if (EditItemID == 0) {
1691         return ID;
1692     }
1693 
1694     // Check if a predefined window exists
1695     if (EditWindow) {
1696 
1697         // Move the window to the correct position
1698         PlaceEditWindow ();
1699 
1700         // Allow editing the value
1701         TextEdit* P = (TextEdit*) EditWindow->ForcedItemWithID (EditItemID);
1702         P->SetValue (SValue);
1703         P->Edit (Abort);
1704 
1705         // if no abort, set the value and return the id
1706         if (Abort) {
1707             Result = 0;
1708         } else {
1709             SetValue (P->GetValue ());
1710             Result = ID;
1711         }
1712 
1713     } else {
1714 
1715         // No item defined, we have to create one
1716         u16 Len = ItemWidth - MinWidth () - 1;
1717         if (Len > InputLength + 1) {
1718             Len = InputLength + 1;
1719         }
1720         TextEdit* P = new TextEdit ("", EditItemID, InputLength, Len, NULL);
1721 
1722         // Set the allowed characters for input
1723         P->SetAllowedChars (AllowedChars);
1724 
1725         // Insert the item into the owner window
1726         Owner->AddItem (P);
1727 
1728         // Set the position of the newly created item
1729         P->SetPos (ItemX + ItemWidth - P->GetWidth (), ItemY);
1730 
1731         // Deselect "this"
1732         Deselect ();
1733 
1734         // Transfer the values from "this" to the new item. Calling
1735         // SetValue will also draw the edit item
1736         P->SetValue (SValue);
1737 
1738         // allow editing
1739         P->Edit (Abort);
1740 
1741         // Get the edited value if the editing was not aborted
1742         if (Abort) {
1743             Result = 0;
1744         } else {
1745             SetValue (P->GetValue ());
1746             Result = ID;
1747         }
1748 
1749         // Delete the edit item from the owners list
1750         Owner->DeleteItem (P);
1751 
1752         // Select "this". This redraws the item and clears the edit field
1753         Select ();
1754 
1755     }
1756 
1757     // Return the result
1758     return Result;
1759 
1760 }
1761 
1762 
1763 
1764