3d537bfb92f3bc74f735a00a3031100d335e6118
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / item / dialog.c
1 // Note: this class is called Dialog, but it can also handle a tab under the following conditions:
2 // - isTabRoot is 0
3 // - backgroundImage is the tab's background
4 // - closable is 0
5 // - rootDialog is 0
6 // - title is ""
7 // - marginTop is 
8 // - intendedHeight ends up to be the tab's actual height, or at least close
9 // - titleFontSize is 0
10 // - marginTop cancels out as much of titleHeight as needed (that is, it should be actualMarginTop - titleHeight)
11 // To ensure the latter, you best create all tabs FIRST and insert the tabbed
12 // control to your dialog THEN - with the right height
13 //
14 // a subclass may help with using this as a tab
15
16 #ifdef INTERFACE
17 CLASS(Dialog) EXTENDS(InputContainer)
18         METHOD(Dialog, configureDialog, void(entity)) // no runtime configuration, all parameters are given in the code!
19         METHOD(Dialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
20         METHOD(Dialog, keyDown, float(entity, float, float, float))
21         METHOD(Dialog, close, void(entity))
22         METHOD(Dialog, addItemSimple, void(entity, float, float, float, float, entity, vector))
23
24         METHOD(Dialog, TD, void(entity, float, float, entity))
25         METHOD(Dialog, TDNoMargin, void(entity, float, float, entity, vector))
26         METHOD(Dialog, TDempty, void(entity, float))
27         METHOD(Dialog, setFirstColumn, void(entity, float))
28         METHOD(Dialog, TR, void(entity))
29         METHOD(Dialog, gotoRC, void(entity, float, float))
30
31         ATTRIB(Dialog, isTabRoot, float, 1)
32         ATTRIB(Dialog, closeButton, entity, NULL)
33         ATTRIB(Dialog, intendedHeight, float, 0)
34         ATTRIB(Dialog, itemOrigin, vector, '0 0 0')
35         ATTRIB(Dialog, itemSize, vector, '0 0 0')
36         ATTRIB(Dialog, itemSpacing, vector, '0 0 0')
37         ATTRIB(Dialog, currentRow, float, 0)
38         ATTRIB(Dialog, currentColumn, float, 0)
39         ATTRIB(Dialog, firstColumn, float, 0)
40
41         // to be customized
42         ATTRIB(Dialog, closable, float, 1)
43         ATTRIB(Dialog, title, string, "Form1") // ;)
44         ATTRIB(Dialog, color, vector, '1 0.5 1')
45         ATTRIB(Dialog, intendedWidth, float, 0)
46         ATTRIB(Dialog, rows, float, 3)
47         ATTRIB(Dialog, columns, float, 2)
48
49         ATTRIB(Dialog, marginTop, float, 0) // pixels
50         ATTRIB(Dialog, marginBottom, float, 0) // pixels
51         ATTRIB(Dialog, marginLeft, float, 0) // pixels
52         ATTRIB(Dialog, marginRight, float, 0) // pixels
53         ATTRIB(Dialog, columnSpacing, float, 0) // pixels
54         ATTRIB(Dialog, rowSpacing, float, 0) // pixels
55         ATTRIB(Dialog, rowHeight, float, 0) // pixels
56         ATTRIB(Dialog, titleHeight, float, 0) // pixels
57         ATTRIB(Dialog, titleFontSize, float, 0) // pixels; if 0, title causes no margin
58         ATTRIB(Dialog, zoomedOutTitleBarPosition, float, 0)
59         ATTRIB(Dialog, zoomedOutTitleBar, float, 0)
60
61         ATTRIB(Dialog, backgroundImage, string, string_null)
62         ATTRIB(Dialog, borderLines, float, 1)
63         ATTRIB(Dialog, closeButtonImage, string, string_null)
64
65         ATTRIB(Dialog, frame, entity, NULL)
66 ENDCLASS(Dialog)
67 #endif
68
69 #ifdef IMPLEMENTATION
70 void Dialog_Close(entity button, entity me)
71 {
72         me.close(me);
73 }
74
75 void Dialog_fill(entity me)
76 {
77 }
78
79 void Dialog_addItemSimple(entity me, float row, float col, float rowspan, float colspan, entity e, vector v)
80 {
81         //print(vtos(me.itemSpacing), " ", vtos(me.itemSize), "\n");
82         vector o, s;
83         o = me.itemOrigin + eX * ( col          * me.itemSpacing_x) + eY * ( row          * me.itemSpacing_y);
84         s = me.itemSize   + eX * ((colspan - 1) * me.itemSpacing_x) + eY * ((rowspan - 1) * me.itemSpacing_y);
85         o_x -= 0.5 * (me.itemSpacing_x - me.itemSize_x) * v_x;
86         s_x +=       (me.itemSpacing_x - me.itemSize_x) * v_x;
87         o_y -= 0.5 * (me.itemSpacing_y - me.itemSize_y) * v_y;
88         s_y +=       (me.itemSpacing_y - me.itemSize_y) * v_y;
89         me.addItem(me, e, o, s, 1);
90 }
91
92 void Dialog_gotoRC(entity me, float row, float col)
93 {
94         me.currentRow = row;
95         me.currentColumn = col;
96 }
97
98 void Dialog_TR(entity me)
99 {
100         me.currentRow += 1;
101         me.currentColumn = me.firstColumn;
102 }
103
104 void Dialog_TD(entity me, float rowspan, float colspan, entity e)
105 {
106         me.addItemSimple(me, me.currentRow, me.currentColumn, rowspan, colspan, e, '0 0 0');
107         me.currentColumn += colspan;
108 }
109
110 void Dialog_TDNoMargin(entity me, float rowspan, float colspan, entity e, vector v)
111 {
112         me.addItemSimple(me, me.currentRow, me.currentColumn, rowspan, colspan, e, v);
113         me.currentColumn += colspan;
114 }
115
116 void Dialog_setFirstColumn(entity me, float col)
117 {
118         me.firstColumn = col;
119 }
120
121 void Dialog_TDempty(entity me, float colspan)
122 {
123         me.currentColumn += colspan;
124 }
125
126 void Dialog_configureDialog(entity me)
127 {
128         entity closebutton;
129         float absWidth, absHeight;
130
131         me.frame = spawnBorderImage();
132         me.frame.configureBorderImage(me.frame, me.title, me.titleFontSize, me.color, me.backgroundImage, me.borderLines * me.titleHeight);
133         me.frame.zoomedOutTitleBarPosition = me.zoomedOutTitleBarPosition;
134         me.frame.zoomedOutTitleBar = me.zoomedOutTitleBar;
135         me.frame.alpha = me.alpha;
136         me.addItem(me, me.frame, '0 0 0', '1 1 0', 1);
137
138         if not(me.titleFontSize)
139                 me.titleHeight = 0; // no title bar
140
141         absWidth = me.intendedWidth * conwidth;
142         absHeight = me.borderLines * me.titleHeight + me.marginTop + me.rows * me.rowHeight + (me.rows - 1) * me.rowSpacing + me.marginBottom;
143         me.itemOrigin  = eX * (me.marginLeft / absWidth)
144                        + eY * ((me.borderLines * me.titleHeight + me.marginTop) / absHeight);
145         me.itemSize    = eX * ((1 - (me.marginLeft + me.marginRight + me.columnSpacing * (me.columns - 1)) / absWidth) / me.columns)
146                        + eY * (me.rowHeight / absHeight);
147         me.itemSpacing = me.itemSize
148                        + eX * (me.columnSpacing / absWidth)
149                        + eY * (me.rowSpacing / absHeight);
150         me.intendedHeight = absHeight / conheight;
151         me.currentRow = -1;
152         me.currentColumn = -1;
153
154         me.fill(me);
155
156         if(me.closable)
157         {
158                 closebutton = me.closeButton = spawnButton();
159                 closebutton.configureButton(closebutton, "Close", 0, me.closeButtonImage);
160                 closebutton.onClick = Dialog_Close; closebutton.onClickEntity = me;
161                 closebutton.srcMulti = 0;
162                 me.addItem(me, closebutton, '0 0 0', '1 1 0', 1); // put it as LAST
163         }
164
165         me.frame.closeButton = closebutton;
166 }
167
168 void Dialog_close(entity me)
169 {
170         if(me.parent.instanceOfNexposee)
171         {
172                 ExposeeCloseButton_Click(me, me.parent);
173         }
174         else if(me.parent.instanceOfModalController)
175         {
176                 DialogCloseButton_Click(me, me);
177         }
178 }
179
180 float Dialog_keyDown(entity me, float key, float ascii, float shift)
181 {
182         if(me.closable)
183         {
184                 if(key == K_ESCAPE)
185                 {
186                         me.close(me);
187                         return 1;
188                 }
189         }
190         return SUPER(Dialog).keyDown(me, key, ascii, shift);
191 }
192 #endif