ecere/gui/drivers/XInterface: Fixed uninitialized warnings
[sdk] / ecere / src / gui / controls / DropBox.ec
1 namespace gui::controls;
2
3 import "Window"
4
5 #include <stdarg.h>
6
7 //#define BTN_WIDTH       20
8 #define BTN_WIDTH       16
9 #define ROW_HEIGHT      listBox.rowHeight /*16*/
10
11 default:
12 extern int __ecereVMethodID_class_OnDisplay;
13 extern int __ecereVMethodID_class_OnGetString;
14
15 private:
16
17 class DropBoxBits { bool noHighlight:1, noStipple:1, editText:1, activeColor:1, showNone:1, changeContents:1; };
18
19 public class DropBox : CommonControl
20 {
21    tabCycle = true;
22    borderStyle = deep;
23    style.activeColor = true;
24
25    class_property(icon) = "<:ecere>controls/dropBox.png";
26
27    watch(foreground)     { listBox.foreground = foreground;         if(editBox) editBox.foreground = foreground; };
28    watch(background)     { listBox.background = background;         if(editBox) editBox.background = background; };
29    watch(selectionColor) { listBox.selectionColor = selectionColor; if(editBox) editBox.selectionColor = selectionColor; };
30    watch(selectionText)  { listBox.selectionText = selectionText;   if(editBox) editBox.selectionText = selectionText; };
31    watch(opacity)        { listBox.opacity = opacity;               if(editBox) editBox.opacity = opacity; };
32
33 public:
34    property bool activeStipple
35    {
36       property_category $"Appearance"
37       set
38       {
39          style.noStipple = !value;
40          Update(null);
41       }
42       get { return !style.noStipple; }
43    };
44    property bool showButton
45    {
46       property_category $"Appearance"
47       set
48       {
49          button.visible = value;
50          listBox.borderStyle = value ? contour : none;
51       }
52       get { return button.visible; }
53    };
54    property Alignment alignment
55    {
56       property_category $"Appearance"
57       set
58       {
59          alignment = value;
60          if(field)
61             field.alignment = value;
62       }
63       get { return alignment; }
64    };
65    property bool noHighlight
66    {
67       property_category $"Appearance"
68       set
69       {
70          if(this)
71          {
72             style.noHighlight = value;
73             listBox.fullRowSelect = !value;
74             Update(null);
75          }
76       }
77       get { return style.noHighlight; }
78    };
79    property bool activeColor
80    {
81       property_category $"Appearance"
82       set
83       {
84          if(this)
85          {
86             style.activeColor = value;
87             Update(null);
88          }
89       }
90       get { return style.activeColor; }
91    };
92    property DataRow currentRow
93    {
94       property_category $"Private"
95       set
96       {
97          if(this)
98          {
99             currentRow = value;
100             listBox.currentRow = value ? value : (style.showNone ? noneRow : null);
101             if(style.editText && style.changeContents)
102             {
103                char tempString[4096];
104                if(currentRow)
105                   editBox.contents = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, currentRow.GetData(null), tempString, null, null);
106                else
107                   editBox.contents = "";
108             }
109             Update(null);
110             if(style.editText)
111             {
112                if(editBox.modifiedDocument)
113                {
114                   NotifyTextEntry(master, this, editBox.contents, false);
115                   editBox.modifiedDocument = false;
116                }
117                // editBox.Deactivate();
118             }
119          }
120       }
121       get { return currentRow; }
122    };
123    property DataRow firstRow { get { return this ? listBox.firstRow : null; } };
124    property DataRow lastRow { get { return this ? listBox.lastRow : null; } };
125    property const char * contents { property_category $"Data" set { if(editBox) editBox.contents = value; } get { return editBox ? editBox.contents : null; } };
126    property bool editText
127    {
128       property_category $"Behavior"
129       set
130       {
131          if(this)
132          {
133             if(value)
134             {
135                if(!editBox)
136                {
137                   editBox = EditBox
138                   {
139                      this, textHorzScroll = true, borderStyle = 0;
140                      anchor = Anchor { left = 0, top = 0, right = BTN_WIDTH, bottom = 0 };
141                      // visible = false, modifyVirtualArea = false;
142                      foreground = foreground;
143                      background = background;
144                      selectionColor = selectionColor;
145                      selectionText = selectionText;
146                   };
147                   incref editBox;
148                   editBox.Create();
149                   button.inactive = false;
150                }
151                style.editText = true;
152                tabCycle = false;
153             }
154             else
155             {
156                if(editBox)
157                {
158                   editBox.Destroy(0);
159                   delete editBox;
160                   button.inactive = true;
161                }
162                style.editText = false;
163             }
164          }
165       }
166       get { return style.editText; }
167    };
168    property EditBox editBox { get { return editBox; } }
169    property Seconds typingTimeout { property_category $"Behavior" set { listBox.typingTimeout = value; } get { return listBox.typingTimeout; } };
170    property int rowHeight { property_category $"Appearance" set { listBox.rowHeight = value; } get { return listBox.rowHeight; } };
171    property int maxShown
172    {
173       property_category $"Behavior"
174       set
175       {
176          listBoxMaxShown = value;
177          OnPosition(position.x, position.y, clientSize.w, clientSize.h);
178       }
179       get { return listBoxMaxShown; }
180    };
181    property Window pullDown
182    {
183       get { return pulledWindow; }
184    }
185    property bool showNone
186    {
187       set
188       {
189          if(value != style.showNone)
190          {
191             if(style.showNone)
192             {
193                listBox.DeleteRow(noneRow);
194                noneRow = null;
195             }
196             style.showNone = value;
197             if(value)
198             {
199                noneRow = listBox.AddRowNone();
200             }
201          }
202       }
203       get { return style.showNone; }
204    }
205    property Color selectionColor { set { selectionColor = value; } get { return selectionColor; } isset { return selectionColor ? true : false; } };
206    property Color selectionText  { set { selectionText = value; } get { return selectionText; } isset { return selectionText ? true : false; } };
207    property bool changeContents
208    {
209       set { style.changeContents = value; }
210       get { return style.changeContents; }
211    }
212
213    property ListBox listBox { get { return listBox; } }
214
215    property int rowCount { get { return listBox.rowCount; } }
216
217    // Notifications
218    virtual bool Window::NotifySelect(DropBox dropBox, DataRow row, Modifiers mods);
219    virtual bool Window::NotifyClose(DropBox dropBox);
220    virtual bool Window::NotifyHighlight(DropBox dropBox, DataRow row, Modifiers mods);
221    virtual bool Window::NotifyTextEntry(DropBox dropBox, const char * string, bool confirmed);
222
223    virtual Window OnDropDown()
224    {
225       // NASTY BUG ON WINDOWS IN PROPERTIES SHEET IF WE DON'T RECREATE THE LISTBOX HERE
226       // To reproduce, comment out, select borderStyle property, alt-tab to another program, come back, drop down
227       // The listBox goes annoyingly to 0, 0
228       listBox.Destroy(0);
229       listBox.Create();
230
231       ResizeListbox();
232       // listBox.visible = true;
233       return listBox;
234    }
235
236    virtual void OnCloseDropDown(Window pullDown)
237    {
238       listBox.visible = false;
239       if(style.editText)
240       {
241          editBox.ActivateEx(true, false, false, false, null, null);
242          editBox.SelectAll();
243       }
244    }
245
246    // Methods
247    DataRow AddStringf(const char * format, ...)
248    {
249       if(this)
250       {
251          DataRow row;
252
253          char string[MAX_F_STRING];
254          va_list args;
255
256          va_start(args, format);
257          vsnprintf(string, sizeof(string), format, args);
258          string[sizeof(string)-1] = 0;
259          va_end(args);
260
261          row = AddRow();
262          row.SetData(null, string);
263          return row;
264       }
265       return null;
266    }
267
268    DataRow AddString(const char * string)
269    {
270       if(this)
271       {
272          DataRow row;
273          row = AddRow();
274          row.SetData(null, string);
275          return row;
276       }
277       return null;
278    }
279
280    void DeleteRow(DataRow row)
281    {
282       if(!row) row = currentRow;
283       listBox.DeleteRow(row);
284       /*
285       if(row == currentRow)
286          currentRow = null;*/
287       Update(null);
288    }
289
290    // Convenience function using current rows
291    int64 GetTag()
292    {
293       return currentRow.tag;
294    }
295
296    void * SetData(DataField field, any_object data)
297    {
298       if(this)
299       {
300          if(currentRow)
301             return currentRow.SetData(field, data);
302       }
303       return null;
304    }
305
306    any_object GetData(DataField field)
307    {
308       return this ? currentRow.GetData(field) : null;
309    }
310
311    void Sort(DataField field, int order)
312    {
313       listBox.Sort(field, order);
314    }
315
316    void AddField(DataField field)
317    {
318       if(this)
319       {
320          if(!field)
321             field = DataField { alignment = alignment };
322
323          listBox.AddField(field);
324          this.field = listBox.firstField;
325          dataType = this.field.dataType;
326       }
327    }
328
329    DataRow AddRow()
330    {
331       DataRow row = null;
332       if(this)
333       {
334          row = listBox.AddRow();
335          OnPosition(position.x, position.y, clientSize.w, clientSize.h);
336       }
337       return row;
338    }
339
340    DataRow AddRowAfter(DataRow after)
341    {
342       DataRow row = null;
343       if(this)
344       {
345          row = listBox.AddRowAfter(after);
346          OnPosition(position.x, position.y, clientSize.w, clientSize.h);
347       }
348       return row;
349    }
350
351    int GetRowCount()
352    {
353       return listBox.rowCount;
354    }
355
356    void Clear()
357    {
358       if(this)
359       {
360          Window master = this.master;
361          listBox.Clear();
362
363          if(currentRow && master)
364          {
365             currentRow = null;
366             NotifySelect(master, this, null, 0);
367          }
368          currentRow = null;
369          if(style.editText && style.changeContents)
370             editBox.contents = "";
371          Update(null);
372          if(style.showNone)
373             noneRow = listBox.AddRowNone();
374       }
375    }
376
377    DataRow FindRow(int64 tag)
378    {
379       if(this)
380       {
381          return listBox.FindRow(tag);
382       }
383       return null;
384    }
385
386    DataRow FindSubRow(int64 tag)
387    {
388       if(this)
389       {
390          return listBox.FindSubRow(tag);
391       }
392       return null;
393    }
394
395    // Drop Box Specific
396    void SelectRow(DataRow row)
397    {
398       if(this)
399       {
400          currentRow = row;
401          if(style.editText && style.changeContents)
402          {
403             char tempString[4096];
404             if(currentRow)
405                editBox.contents = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, currentRow.GetData(null), tempString, null, null);
406             else
407                editBox.contents = "";
408          }
409          listBox.SelectRow(currentRow ? currentRow : (style.showNone ? noneRow : null));
410
411          Update(null);
412       }
413    }
414
415    bool Save()
416    {
417       if(editBox && editBox.modifiedDocument)
418       {
419          NotifyTextEntry(master, this, editBox.contents, true);
420          if(editBox)
421             editBox.modifiedDocument = false;
422          return true;
423       }
424       return false;
425    }
426
427 private:
428    DropBox()
429    {
430       listBoxMaxShown = 1000;
431       field = listBox.firstField;
432       dataType = field.dataType;
433       style.changeContents = true;
434       return true;
435    }
436
437    ~DropBox()
438    {
439       delete editBox;
440    }
441
442    void ResizeListbox()
443    {
444       int rowCount = Min(listBox.rowCount, listBoxMaxShown);
445       int height = rowCount * ROW_HEIGHT;
446       listBox.clientSize = { clientSize.w, height };
447    }
448
449    void OnPosition(int x, int y, int width, int height)
450    {
451       if(pulledWindow)
452       {
453          int lx = absPosition.x - guiApp.desktop.absPosition.x;
454          int ly = absPosition.y - guiApp.desktop.absPosition.y;
455          int availHeight = pulledWindow.parent.clientSize.h;
456          int height = pulledWindow.clientSize.h;
457
458          // If it won't fit below but fits above, place it above...
459          if(ly + size.h + height > availHeight && height < ly)
460             ly -= height;
461          else
462          {
463             ly += size.h;
464             if(ly + height > availHeight)
465                height = ((availHeight - ly) / ROW_HEIGHT) * ROW_HEIGHT;
466          }
467
468          if(!pulledWindow.initSize.w)
469             pulledWindow.size.w = size.w;
470          else
471             // Align it to the right (pull down button)
472             lx -= pulledWindow.size.w - size.w;
473          pulledWindow.position = { lx, ly };
474          pulledWindow.clientSize = { pulledWindow.clientSize.w, height };
475       }
476    }
477
478    bool OnKeyDown(Key key, unichar ch)
479    {
480       switch(key)
481       {
482          case hotKey:
483          case space:
484          case right:
485          case escape:
486             // ADDED THIS CHECK HERE TO NAVIGATE THROUGH GRID LISTBOX
487             if(key == right)
488             {
489                if(eClass_IsDerived(master._class, class(DataBox)))
490                {
491                   if(eClass_IsDerived(master.master._class, class(ListBox)))
492                      return true;
493                }
494                else if(eClass_IsDerived(master._class, class(ListBox)))
495                   return true;
496             }
497             if(key == escape && !pulledWindow)
498             {
499                //if(editBox) button.Deactivate();
500                //if(editBox) button.Activate();
501                if(style.editText)
502                {
503                   if(editBox.modifiedDocument)
504                   {
505                      NotifyTextEntry(master, this, editBox.contents, false);
506                      editBox.modifiedDocument = false;
507                   }
508                   //editBox.Deactivate();
509                }
510                break;
511             }
512             if(style.editText && (key == space || key == right))
513                break;
514
515             if(pulledWindow)
516             {
517                OnCloseDropDown(pulledWindow);
518                pulledWindow = null;
519                button.checked = false;
520                NotifyClose(master, this);
521
522                if(style.editText)
523                {
524                   if(editBox.modifiedDocument)
525                   {
526                      NotifyTextEntry(master, this, editBox.contents, false);
527                      editBox.modifiedDocument = false;
528                   }
529                   editBox.Activate();
530                }
531             }
532             else
533             {
534                listBox.currentRow = currentRow ? currentRow : (style.showNone ? noneRow : null);
535                pulledWindow = OnDropDown();
536                OnPosition(position.x, position.y, clientSize.w, clientSize.h);
537                if(pulledWindow) pulledWindow.visible = true;
538                button.checked = true;
539             }
540             Update(null);
541             return false;
542          case enter:
543          case keyPadEnter:
544             if(!pulledWindow)
545             {
546                if(style.editText)
547                {
548                   if(editBox.modifiedDocument)
549                   {
550                      NotifyTextEntry(master, this, editBox.contents, true);
551                      editBox.modifiedDocument = false;
552                      //editBox.Deactivate();
553                   }
554
555                   // Add code to look through listbox and set current row if listbox is used
556                }
557                break;
558             }
559             else
560             {
561                incref this;
562
563                OnCloseDropDown(pulledWindow);
564                pulledWindow = null;
565                button.checked = false;
566                Update(null);
567
568                if(!NotifyClose(master, this))
569                {
570                   delete this;
571                   return false;
572                }
573
574                // Moved this from below NotifySelect
575                currentRow = listBox.currentRow;
576                if(currentRow && currentRow.noneRow) currentRow = null;
577                if(style.editText && style.changeContents)
578                {
579                   char tempString[4096];
580                   if(currentRow)
581                      editBox.contents = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, currentRow.GetData(null), tempString, null, null);
582                   else
583                      editBox.contents = "";
584                }
585
586                NotifySelect(master, this, currentRow, key.modifiers | { closingDropDown = true });
587
588                delete this;
589                return false;
590             }
591             return false;
592          //default:
593          //   return listBox.OnKeyDown(key, ch);
594       }
595       return true;
596    }
597
598    void OnApplyGraphics()
599    {
600       button.anchor = { right = 0, top = 0, bottom = 0 };
601       button.size = { guiApp.textMode ? 8 : BTN_WIDTH, 0 };
602    }
603
604    /*Timer timer
605    {
606       window = this, delay = 0.01;
607
608       bool DelayExpired()
609       {
610          background = active ? red : lime;
611          parent.parent.background = parent.parent.active ? red : lime;
612          guiApp.desktop.Update(null);
613          return true;
614       }
615    };*/
616
617    void OnRedraw(Surface surface)
618    {
619       //timer.started = true;
620       if(!style.editText)
621       {
622          if(active && !pulledWindow/*listBox.visible*/)
623          {
624             if(style.activeColor)
625             {
626                surface.SetBackground(selectionColor ? selectionColor : SELECTION_COLOR);
627                if(!style.noHighlight || !currentRow)
628                {
629                   surface.Area(0,0, clientSize.w-1,clientSize.h-1);
630                }
631             }
632          }
633          if(!isEnabled)
634             surface.SetForeground(Color { 85,85,85 } );
635          else
636             surface.SetForeground((active && style.activeColor && !pulledWindow /*listBox.visible*/) ? selectionText : foreground);
637          surface.TextOpacity(true);
638
639          if(currentRow)
640          {
641             DataDisplayFlags displayFlags { active = active, current = true, dropBox = true, selected = true, fullRow = true };
642             ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)dataType._vTbl[__ecereVMethodID_class_OnDisplay])(dataType, currentRow.GetData(null), surface, 3,
643                1+(clientSize.h - listBox.rowHeight) / 2, clientSize.w - (button.visible ? button.size.w : 0) - 3,
644                field.userData, alignment, displayFlags);
645          }
646          else
647             surface.WriteText(2,2, "(none)", 6);
648
649          if(!style.noStipple && (!style.noHighlight || !currentRow))
650          {
651             surface.SetForeground(0xFFFFFF80);
652             if(active && !pulledWindow /*listBox.visible*/)
653             {
654                surface.Rectangle(0,0,clientSize.w-1-BTN_WIDTH,clientSize.h-1);
655                surface.SetForeground(black);
656                surface.LineStipple(0xAAAA);
657                surface.Rectangle(0,0,clientSize.w-1-BTN_WIDTH,clientSize.h-1);
658                surface.LineStipple(0);
659             }
660          }
661       }
662    }
663
664    bool OnResizing(int *width, int *height)
665    {
666       int rowHeight = 0;
667
668       display.FontExtent(fontObject, "W", 1, null, &rowHeight);
669       rowHeight = Max(rowHeight, 16);
670
671       if(!*width) *width = Max(*width, rowHeight * 100 / 16);
672
673       //if(!*width) *width = Max(*width, 100);
674       //if(!*height) *height = Max(*height, 20);
675       if(!*height) *height = Max(*height, rowHeight * 20 / 16);
676
677       return true;
678    }
679
680    /*
681    watch(font)
682    {
683       SetInitSize(initSize);
684    };
685    */
686
687    bool OnLeftButtonDown(int x, int y, Modifiers mods)
688    {
689       Update(null);
690       if(pulledWindow)
691       {
692          OnCloseDropDown(pulledWindow);
693          button.checked = false;
694          pulledWindow = null;
695
696          if(!NotifyClose(master, this))
697             return false;
698       }
699       else
700       {
701          listBox.currentRow = currentRow ? currentRow : (style.showNone ? noneRow : null);
702          pulledWindow = OnDropDown();
703          OnPosition(position.x, position.y, clientSize.w, clientSize.h);
704          if(pulledWindow) pulledWindow.visible = true;
705          if(listBox.freeSelect)
706             pulledWindow.OnLeftButtonDown(-2,-2, 0);
707          button.checked = true;
708       }
709       return true;
710    }
711
712    bool OnKeyHit(Key key, unichar ch)
713    {
714       DataRow currentRow = this.currentRow;
715
716       if(!pulledWindow /*listBox.visible*/)
717       {
718          int c;
719          if(style.showNone && !currentRow) currentRow = noneRow;
720
721          switch(key)
722          {
723             case wheelDown:
724             case down: currentRow = currentRow ? currentRow.next : null; break;
725             case wheelUp:
726             case up:   currentRow = currentRow ? currentRow.prev : null; break;
727             case pageDown:
728                for(c = 0; c<listBoxMaxShown && currentRow && currentRow.next; c++, currentRow = currentRow.next);
729                break;
730             case pageUp:
731                for(c = 0; c<listBoxMaxShown && currentRow && currentRow.prev; c++, currentRow = currentRow.prev);
732                break;
733             case end:
734                for(; currentRow && currentRow.next; currentRow = currentRow.next);
735                break;
736             case home:
737                for(; currentRow && currentRow.prev; currentRow = currentRow.prev);
738                break;
739             default:
740                if(!editBox || button.active || !editBox.active || editBox.OnKeyHit(key, ch))
741                {
742                   return listBox.OnKeyHit(key, ch);
743                }
744                else
745                   return false;
746          }
747          if(currentRow)
748          {
749             if(currentRow.noneRow) currentRow = null;
750             property::currentRow = currentRow;
751             //return
752                NotifySelect(master, this, currentRow, key.modifiers);
753             //return false;
754          }
755          return false;
756       }
757       else
758       {
759          if(listBox.vertScroll)
760          {
761             if(key == wheelUp)
762                listBox.vertScroll.Action(up, 0, key);
763             else if(key == wheelDown)
764                listBox.vertScroll.Action(down, 0, key);
765          }
766          return listBox.OnKeyHit(key, ch);
767       }
768       return true;
769    }
770
771    bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
772    {
773       // WAS !active JUST MISSING HERE ?
774       if(!active && style.editText)
775       {
776          if(editBox.modifiedDocument)
777          {
778             if(editBox) editBox.modifiedDocument = false;
779             NotifyTextEntry(master, this, editBox.contents, true); //false);
780             // MOVED THIS ABOVE TO AVOID INFINITE RECURSION
781             // if(editBox) editBox.modifiedDocument = false;
782          }
783          //editBox.Deactivate();
784       }
785       Update(null);
786       return true;
787    }
788
789    public Button button
790    {
791       this, toggle = true, bevel = true, inactive = true,
792       anchor = Anchor { right = 0, top = 0, bottom = 0 },
793       size = Size { BTN_WIDTH, 0 },
794       symbol = 25;
795       bitmap = { "<:ecere>elements/arrowDown.png" };
796
797       bool NotifyPushed(Button control, int x, int y, Modifiers mods)
798       {
799          if(pulledWindow)
800          {
801             OnCloseDropDown(pulledWindow);
802             pulledWindow = null;
803             button.checked = false;
804             NotifyClose(master, this);
805          }
806          else
807          {
808             incref this;
809             if(editBox && editBox.modifiedDocument)
810             {
811                NotifyTextEntry(master, this, editBox.contents, true);
812                editBox.modifiedDocument = false;
813             }
814             pulledWindow = OnDropDown();
815             if(pulledWindow)
816             {
817                OnPosition(position.x, position.y, clientSize.w, clientSize.h);
818                if(listBox.freeSelect)
819                   pulledWindow.OnLeftButtonDown(-2,-2, 0);
820                button.checked = true;
821                pulledWindow.visible = true;
822             }
823             delete this;
824          }
825          Update(null);
826          return true;
827       }
828    };
829
830    ListBox listBox
831    {
832       master = this, fullRowSelect = true, freeSelect = true, /* noHighlight = style.noHighlight , */
833       interim = true, hasVertScroll = true, borderStyle = contour, position = { absPosition.x, absPosition.y + size.h },
834       size.w = size.w, visible = false;
835
836       bool NotifyActivate(Window control, bool active, Window swap)
837       {
838          if(!active)
839          {
840             Update(null);
841             if(swap != button && swap != this)
842             {
843                if(editBox && editBox.modifiedDocument)
844                {
845                   NotifyTextEntry(master, this, editBox.contents, true);
846                   editBox.modifiedDocument = false;
847                }
848
849                OnCloseDropDown(pulledWindow);
850                pulledWindow = null;
851                button.checked = false;
852                NotifyClose(master, this);
853             }
854          }
855          return true;
856       }
857
858       bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
859       {
860          Update(null);
861
862          // Add code to set text to list box contents if it has an editbox
863
864          if(pulledWindow)
865          {
866             OnCloseDropDown(pulledWindow);
867             pulledWindow = null;
868             button.checked = false;
869             mods.closingDropDown = true;
870             if(!NotifyClose(master, this))
871                return false;
872          }
873          currentRow = (row && !row.noneRow) ? row : null;
874          if(style.editText && style.changeContents)
875          {
876             char tempString[4096];
877             if(currentRow)
878                editBox.contents = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, currentRow.GetData(null), tempString, null, null);
879             else
880                editBox.contents = "";
881             if(active)
882                editBox.SelectAll();
883          }
884          button.Deactivate();
885          return NotifySelect(master, this, currentRow, mods);
886       }
887
888       bool NotifyHighlight(ListBox control, DataRow row, Modifiers mods)
889       {
890          return NotifyHighlight(master, this, row, mods);
891       }
892
893       bool NotifyKeyDown(ListBox listBox, DataRow selection, Key key, unichar ch)
894       {
895          return OnKeyDown(key, ch);
896          //return true;
897       }
898    };
899
900    bool OnPostCreate()
901    {
902       if(font)
903          listBox.font = { font.faceName, font.size };
904       return true;
905    }
906
907    DropBoxBits style;
908    Window pulledWindow;
909    DataRow currentRow;
910    int listBoxMaxShown;
911    Class dataType;
912    DataField field;
913    EditBox editBox;
914    Alignment alignment;
915    DataRow noneRow;
916    ColorAlpha selectionColor, selectionText;
917
918    selectionColor = SELECTION_COLOR;
919    selectionText = SELECTION_TEXT;
920 };