3b7ffdeb784c4e82cd5ccf7df4140e9338c50f5c
[sdk] / ecere / src / gui / dialogs / MessageBox.ec
1 namespace gui::dialogs;
2
3 import "Window"
4
5 static class MsgLine : struct
6 {
7    MsgLine prev, next;
8    char * string;
9    int len;
10 };
11
12 public enum MessageBoxType { ok, yesNo, okCancel, yesNoCancel };
13 public class MessageBox : Window
14 {
15    background = formColor;
16    hasClose = true;
17    tabCycle = true;
18    nativeDecorations = true;
19
20 public:
21    property MessageBoxType type { set { style = value; } };
22    property char * contents
23    {
24       set
25       {
26          FreeLines();
27          if(value)
28          {
29             int len = strlen(value);
30             int start = 0;
31             int c;
32             for(c = 0; c <= len; c++)
33             {
34                if(c == len || value[c] == '\n')
35                {
36                   MsgLine line { };
37                   lines.Add(line);
38                   if(line)
39                   {
40                      line.len = c - start;
41                      line.string = new char[line.len+1];
42                      CopyBytes(line.string, value + start, line.len);
43                      line.string[line.len] = '\0';
44                      start = c+1;
45                   }
46                }
47             }
48          }
49       }
50    };
51
52 private:
53    MessageBoxType style;
54    OldList lines;
55    int totalWidth, totalHeight, lineHeight;
56
57    ~MessageBox()
58    {
59       FreeLines();
60    }
61
62    bool ButtonActivate(Window control, bool active, Window previous)
63    {
64       control.isDefault = true;
65       return true;
66    }
67
68    bool OnPostCreate()
69    {
70       switch(style)
71       {
72          case yesNo:
73             Button
74             {
75                this, text = $"No", anchor = { horz = 40, bottom = 7 }, size = { 64 }, id = DialogResult::no, hotKey = n;
76                NotifyClicked = ButtonCloseDialog, NotifyActivate = ButtonActivate;
77             }.Create();
78
79             Button
80             {
81                this, isDefault = true, text = $"Yes", anchor = { horz = -40, bottom = 7 }, size = { 64 }, id = DialogResult::yes, hotKey = y;
82                NotifyClicked = ButtonCloseDialog, NotifyActivate = ButtonActivate;
83             }.Create();
84             break;
85          case okCancel:
86             Button
87             {
88                this, text = $"Cancel", anchor = { horz = 40, bottom = 7 }, size = { 64 }, id = DialogResult::cancel, hotKey = escape;
89                NotifyClicked = ButtonCloseDialog, NotifyActivate = ButtonActivate;
90             }.Create();
91
92             Button
93             {
94                this, isDefault = true, text = $"OK", anchor = { horz = -40, bottom = 7 }, size = { 64 }, id = DialogResult::ok, hotKey = o;
95                NotifyClicked = ButtonCloseDialog, NotifyActivate = ButtonActivate;
96             }.Create();
97             break;
98          case yesNoCancel:
99             Button
100             {
101                this, text = $"No", anchor = { bottom = 7 }, size = { 64 }, id = DialogResult::no, hotKey = n;
102                NotifyClicked = ButtonCloseDialog, NotifyActivate = ButtonActivate;
103             }.Create();
104
105             Button
106             {
107                this, text = $"Cancel", anchor = { horz = 72, bottom = 7 }, size = { 64 }, id = DialogResult::cancel, hotKey = escape;
108                NotifyClicked = ButtonCloseDialog, NotifyActivate = ButtonActivate;
109             }.Create();
110
111             Button
112             {
113                this, isDefault = true, text = $"Yes", anchor = { horz = -72, bottom = 7 }, size = { 64 }, id = DialogResult::yes, hotKey = y;
114                NotifyClicked = ButtonCloseDialog, NotifyActivate = ButtonActivate;
115             }.Create();
116             break;
117          case ok:
118             Button
119             {
120                this, isDefault = true, text = $"OK", anchor = { bottom = 7 }, size = { 64 }, id = DialogResult::ok, hotKey = o;
121                NotifyClicked = ButtonCloseDialog, NotifyActivate = ButtonActivate;
122             }.Create();
123             break;
124       }
125       return true;
126    }
127
128    bool OnResizing(int *w, int *h)
129    {
130       if(!totalHeight)
131          OnLoadGraphics();
132       if(style == yesNoCancel)
133          *w = Max(*w, Max(totalWidth, 208) + 24);
134       else
135          *w = Max(*w, Max(totalWidth, 144) + 24);
136
137       *h = Max(*h, Max(totalHeight, 33) + 40);
138       return true;
139    }
140
141    void OnRedraw(Surface surface)
142    {
143       MsgLine line;
144       int y = (clientSize.h - 33 - totalHeight) / 2;
145       for(line = lines.first; line; line = line.next)
146       {
147          surface.WriteText((clientSize.w - totalWidth) / 2, y, line.string, line.len);
148          y += lineHeight;
149       }
150    }
151
152    bool OnLoadGraphics()
153    {
154       MsgLine line;
155       // This is to set minimum client size on X11
156       // Ideally OnLoadGraphics/OnResizing could be called prior to root window creation...
157       Display display = this.display;
158       Font fontObject = this.fontObject;
159       if(!display) display = master.display;
160       if(!fontObject) fontObject = master.fontObject;
161
162       totalHeight = 0;
163       for(line = lines.first; line; line = line.next)
164       {
165          Size size;
166          if(!line.string[0])
167             display.FontExtent(fontObject, " ", 1, (int *)&size.w, (int *)&size.h);
168          else
169             display.FontExtent(fontObject, line.string, strlen(line.string), (int *)&size.w, (int *)&size.h);
170          if(size.h)
171             lineHeight = size.h;
172          totalWidth = Max(totalWidth, size.w);
173          totalHeight += size.h;
174       }
175       return true;
176    }
177
178    void FreeLines()
179    {
180       MsgLine line;
181       for(line = lines.first; line; line = line.next)
182          delete line.string;
183       lines.Free(null);
184    }
185 };