ecere/gui/controls/DataBox: Only setting autoSize on editor if DataBox's autoSize...
[sdk] / ecere / src / gui / controls / DataBox.ec
1 namespace gui::controls;
2
3 import "Window"
4
5 default:
6 extern int __ecereVMethodID_class_OnGetString;
7 extern int __ecereVMethodID_class_OnGetDataFromString;
8 extern int __ecereVMethodID_class_OnCompare;
9 extern int __ecereVMethodID_class_OnSerialize;
10 extern int __ecereVMethodID_class_OnUnserialize;
11 extern int __ecereVMethodID_class_OnFree;
12 extern int __ecereVMethodID_class_OnEdit;
13 extern int __ecereVMethodID_class_OnCopy;
14 extern int __ecereVMethodID_class_OnDisplay;
15 extern int __ecereVMethodID_class_OnSaveEdit;
16 private:
17
18 public class DataBox : CommonControl
19 {
20 public:
21    Class type;
22    void * data;
23    void * fieldData;
24    Window editor;
25    bool readOnly;
26    bool keepEditor;
27    bool autoSize;
28    bool needUpdate;
29    String stringValue;
30    needUpdate = true;
31
32    ~DataBox()
33    {
34       delete stringValue;
35    }
36
37    virtual void SetData(any_object newData, bool closingDropDown)
38    {
39       //((void (*)(void *, void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnCopy])(type, data, newData);
40       needUpdate = true;
41       if(type)
42       {
43          if(type.type == normalClass || type.type == noHeadClass)
44          {
45             if(((void **)data)[0])
46                ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, ((void **)data)[0]);
47             ((void **)data)[0] = newData;
48          }
49          else
50          {
51             // Free old data first
52             ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, data);
53             ((void (*)(void *, void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnCopy])(type, data, newData);
54          }
55       }
56       if(created)
57          NotifyChanged(master, this, closingDropDown);
58       //editor.Activate();
59    }
60
61    bool SaveData()      // TODO: Clear this up, along with Saving DataBox
62    {
63       if(editor && ((bool (*)(void *, void *, Window, void *))(void *)type._vTbl[__ecereVMethodID_class_OnSaveEdit])(type, data, editor, null))
64       {
65          Refresh();
66          NotifyChanged(master, this, false);
67          // Refresh();
68          return true;
69       }
70       return false;
71    }
72
73    void Modified()
74    {
75       NotifyModified(master);
76    }
77
78    void Refresh()
79    {
80       needUpdate = true;
81       if(created)
82       {
83          if(!keepEditor)
84          {
85             editor.Destroy(0);
86             editor = null;
87          }
88          OnPostCreate();
89       }
90    }
91
92    virtual bool Window::NotifyModified();
93    virtual bool Window::NotifyChanged(DataBox dataBox, bool closingDropDown);
94    virtual void OnConfigure(Window editor);
95
96 private:
97    bool inAutoSize;
98
99    watch(background)     { if(editor) editor.background = background; };
100    watch(foreground)     { if(editor) editor.foreground = foreground; };
101    //watch(selectionColor) { if(editor) editor.selectionColor = selectionColor; };
102    //watch(selectionText)  { if(editor) editor.selectionText = selectionText; };
103    watch(opacity)        { if(editor) editor.opacity = opacity; };
104
105    bool OnPostCreate()
106    {
107       // Right now for read-only DataBoxes the only reason we'd want to create an editor is for autoSize purposes, when using the default EditBox editor that supports it.
108       // ( A tweak for enum classes is in typeEdit.ec, as the base class editor invokes it )
109       if(type/* && (!readOnly || (autoSize && type._vTbl[__ecereVMethodID_class_OnEdit] == class(Instance)._vTbl[__ecereVMethodID_class_OnEdit]))*/ &&
110          (type.type == normalClass || type.type == noHeadClass || data))
111       {
112          // IMPORTANT FIX: If keepEditor is true, we were passing editor rather than the editor's current master
113          editor = ((Window (*)(void *, void *, DataBox, void *, int, int, int, int, void*))(void *)type._vTbl[__ecereVMethodID_class_OnEdit])(type,
114             (type.type == normalClass || type.type == noHeadClass) ? (data ? (*(void **)data) : null) : data,
115             this, (keepEditor && editor) ? editor.master : this, 0, 0, clientSize.w, clientSize.h, fieldData);// null);
116          if(editor && readOnly && !eClass_IsDerived(editor._class, class(EditBox)) &&
117                !(autoSize && type._vTbl[__ecereVMethodID_class_OnEdit] == class(Instance)._vTbl[__ecereVMethodID_class_OnEdit]))
118          {
119             editor.Destroy(0);
120             editor = null;
121             return true;
122          }
123          if(editor)
124          {
125             // editor.anchor = { 0, 0, 0, 0 };
126             editor.background = background;
127             editor.foreground = foreground;
128             editor.opacity = opacity;
129             if(eClass_IsDerived(editor._class, class(EditBox)))
130             {
131                ((EditBox)editor).readOnly = readOnly;
132                if(autoSize)
133                   ((EditBox)editor).autoSize = autoSize;
134                ((EditBox)editor).clickThrough = true;
135             }
136             else if(eClass_IsDerived(editor._class, class(Button)) && autoSize)
137                size = editor.size;
138          }
139          else
140          {
141             // TODO: Should returning 0 from OnPostCreate cancel creation?
142             Destroy(0);
143             return false;
144          }
145       }
146       return true;
147    }
148
149    void OnRedraw(Surface surface)
150    {
151       if(type && data && (!editor || !editor.created || editor.anchor.left)) // ColorDropBox lets part of the DataBox show
152       {
153          char tempString[1024];
154          if(type._vTbl[__ecereVMethodID_class_OnDisplay] == class(Instance)._vTbl[__ecereVMethodID_class_OnDisplay])
155          {
156             if(needUpdate)
157             {
158                const String s;
159                if(type.type == noHeadClass || type.type == normalClass)
160                   s = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, *(void **)this.data, tempString, fieldData, null);
161                else
162                   s = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, this.data, tempString, fieldData, null);
163                delete stringValue;
164                stringValue = CopyString(s);
165                needUpdate = false;
166             }
167             ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)class(String)._vTbl[__ecereVMethodID_class_OnDisplay])(class(String), stringValue, surface, 3, 1, clientSize.w, fieldData, type.defaultAlignment, 0);
168          }
169          else
170          {
171             if(type.type == noHeadClass || type.type == normalClass)
172                ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)type._vTbl[__ecereVMethodID_class_OnDisplay])(type, *(void **)this.data, surface, 3, 1, clientSize.w, fieldData, type.defaultAlignment, 0);
173             else
174                ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)type._vTbl[__ecereVMethodID_class_OnDisplay])(type, this.data, surface, 3, 1, clientSize.w, fieldData, type.defaultAlignment, 0);
175          }
176       }
177    }
178
179    void OnDestroy()
180    {
181       editor = null;
182       CommonControl::OnDestroy();
183    }
184
185    void OnPosition(int x, int y, int width, int height)
186    {
187       if(editor)
188          editor.OnPosition(editor.position.x, editor.position.y, editor.size.w, editor.size.h);
189    }
190
191    bool OnKeyHit(Key key, unichar ch)
192    {
193       return editor ? editor.OnKeyHit(key, ch) : true;
194    }
195
196    bool OnKeyDown(Key key, unichar ch)
197    {
198       if((SmartKey)key == enter)
199       {
200          SaveData();
201          return false;
202       }
203       else if((SmartKey)key == escape)
204       {
205          Refresh();
206          return true;
207       }
208       return editor ? editor.OnKeyDown(key, ch) : true;
209    }
210
211    void OnChildResized(Window child, int x, int y, int w, int h)
212    {
213       if(!inAutoSize && autoSize == true)
214       {
215          inAutoSize = true;
216          clientSize = { w, h };
217          inAutoSize = false;
218       }
219    }
220 };
221
222 public class SavingDataBox : DataBox
223 {
224    class_property(icon) = "<:ecere>controls/dataBox.png";
225    borderStyle = deep;
226    bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
227    {
228       if(!active && editor && !editor.modalSlave)
229       {
230          if(!SaveData())
231             Refresh();
232       }
233       return true;
234    }
235
236    bool OnKeyDown(Key key, unichar ch)
237    {
238       if((SmartKey)key == enter)
239       {
240          if(!SaveData())
241             // Force Refresh on Enter if SaveData didn't do it
242             Refresh();
243          return true;
244       }
245       return DataBox::OnKeyDown(key, ch);
246    }
247
248    bool OnResizing(int * w, int * h)
249    {
250       if(!*w || !*h)
251       {
252          int spaceH;
253          display.FontExtent(fontObject, " ", 1, null, &spaceH);
254          if(!*h)
255             *h = spaceH + 2;
256          if(!*w)
257             *w = spaceH * 80 / 14;
258       }
259       return true;
260    }
261 }