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