]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/xforms_resize.C
Really dull and boring header shit
[lyx.git] / src / frontends / xforms / xforms_resize.C
1 /**
2  * \file xforms_resize.C
3  * Read the file COPYING
4  *
5  * \author Angus Leeming 
6  *
7  * Full author contact details are available in file CREDITS
8  */
9
10 #include <config.h>
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 #include "xforms_resize.h"
17
18 #include "LString.h"
19 #include <algorithm>
20 #include <vector>
21 #include FORMS_H_LOCATION
22
23 using std::vector;
24
25 namespace {
26
27 // Returns the FL_OBJECT * of class FL_TABFOLDER if present in the form.
28 // Else 0.
29 FL_OBJECT * find_tabfolder(FL_FORM * form);
30
31 // Takes an FL_OBJECT * folder of class FL_TABFOLDER and calculates how much it
32 // should be scaled to display all the tabs.
33 // Returns 1 if the tabs are alll fully visible.
34 // Nested tabfolders are not considered.
35 double scale_to_fit_tabs(FL_OBJECT * folder);
36
37 // Returns the leaves making up a tabfolder.
38 vector<FL_FORM *> const leaves_in_tabfolder(FL_OBJECT * folder);
39
40 // The labels of each tab in the folder.
41 vector<string> const tab_names(FL_OBJECT * folder);
42
43 } // namespace anon
44
45
46 double scale_to_fit_tabs(FL_FORM * form)
47 {
48         if (!form)
49                 return 1;
50
51         FL_OBJECT * folder = find_tabfolder(form);
52         if (!folder)
53                 return 1;
54
55         double scale = scale_to_fit_tabs(folder);
56
57         vector<FL_FORM *> const leaves = leaves_in_tabfolder(folder);
58         vector<FL_FORM *>::const_iterator it  = leaves.begin();
59         vector<FL_FORM *>::const_iterator end = leaves.end();
60
61         for (; it != end; ++it) {
62                 folder = find_tabfolder(*it);
63                 if (folder)
64                         scale = std::max(scale, scale_to_fit_tabs(folder));
65         }
66
67         return scale;
68 }
69
70
71 void scale_form(FL_FORM * form, double scale_factor)
72 {
73         if (!form)
74                 return;
75
76         fl_scale_form(form, scale_factor, 1);
77
78         FL_OBJECT * folder = find_tabfolder(form);
79         if (!folder)
80                 return;
81
82         vector<FL_FORM *> const leaves = leaves_in_tabfolder(folder);
83         vector<FL_FORM *>::const_iterator it  = leaves.begin();
84         vector<FL_FORM *>::const_iterator end = leaves.end();
85
86         for (; it != end; ++it) {
87                 fl_scale_form(*it, scale_factor, 1);
88         }
89 }
90
91
92 namespace {
93
94 FL_OBJECT * find_tabfolder(FL_FORM * form)
95 {
96         for (FL_OBJECT * ob = form->first; ob; ob = ob->next) {
97                 if (ob->objclass == FL_TABFOLDER)
98                         return ob;
99         }
100
101         return 0;
102 }
103
104
105 // Return the scaling factor needed to render all the tab labels.
106 double scale_to_fit_tabs(FL_OBJECT * folder)
107 {
108         if (folder->objclass != FL_TABFOLDER)
109                 return 1;
110
111         // The problem here is that we can access the names of a tabfolder's
112         // tabs directly (through fl_get_folder_name(folder)), but we
113         // can't access directly the tabs themselves. Nonetheless, they are
114         // made visible as buttons on the parent form, so we can obtain
115         // the style info by a judicious camparison of names. This style info
116         // (label font size, style) is needed to ascertain how much space
117         // the label takes up.
118
119         // The tabfolder makes the tabs (buttons) visible to the parent form,
120         // so to identify them, we need their names.
121         vector<string> const names = tab_names(folder);
122         if (names.empty())
123                 return 1;
124
125         FL_FORM * parent = folder->form;
126         if (!parent)
127                 return 1;
128
129         // Ascertain the style parameters of the tabs.
130         int label_style = FL_BOLD_STYLE;
131         int label_size  = FL_NORMAL_SIZE;
132         int box_width   = 1;
133         // Hard-coded within xforms' fl_create_tabfolder in tabfolder.c.
134         int const tab_padding = 12;
135
136         for (FL_OBJECT * ob = parent->first; ob; ob = ob->next) {
137                 if (!ob->label)
138                         continue;
139
140                 vector<string>::const_iterator it  = names.begin();
141                 vector<string>::const_iterator end = names.end();
142                 it = std::find(it, end, ob->label);
143
144                 if (it == end)
145                         continue;
146
147                 label_style = ob->lstyle;
148                 label_size  = ob->lsize;
149
150                 if (ob->boxtype == FL_UP_BOX || ob->boxtype == FL_DOWN_BOX)
151                         box_width = FL_abs(ob->bw);
152
153                 // achieved all we set out to achieve, so break.
154                 break;
155         }
156         // Hard coded in xforms' get_tabsize in tabfolder.c as
157         // (2 + fudge) * box_width, where fudge is always 1.
158         int const box_width_factor = 3 * box_width;
159
160         // Loop over the names and calculate how much space is needed to display
161         // them.
162         int length = 0;
163
164         vector<string>::const_iterator it  = names.begin();
165         vector<string>::const_iterator end = names.end();
166
167         for (; it != end; ++it) {
168                 int sw, sh;
169
170                 fl_get_string_dimension(label_style, label_size,
171                                         it->c_str(), int(it->size()),
172                                         &sw, &sh);
173
174                 // This is the minimum width the object must be to contain
175                 // the label
176                 length += sw + tab_padding + box_width_factor;
177         }
178
179         // Compare this length to the width of the tabfolder
180         double const scale = double(length) / double(folder->w);
181         return std::max(double(1), scale);
182 }
183
184
185 // A nasty hack for older xforms versions
186 int get_tabfolder_numfolders(FL_OBJECT * folder)
187 {
188 #if FL_VERSION > 0 || FL_REVISION > 88
189         return fl_get_tabfolder_numfolders(folder);
190 #else
191         if (folder->objclass != FL_TABFOLDER)
192                 return 0;
193
194         fl_freeze_form(folder->form);
195         int const saved_folder_id = fl_get_folder_number(folder);
196
197         int num_folders = 0;
198         FL_FORM const * old_leaf = 0;
199         for (;;) {
200                 int const id = num_folders + 1;
201                 fl_set_folder_bynumber(folder, id);
202                 FL_FORM const * const leaf = fl_get_folder(folder);
203                 if (!leaf || leaf == old_leaf) {
204                         // unable to increment succesfully.
205                         break;
206                 }
207                 old_leaf = leaf;
208                 ++num_folders;
209         }
210
211         fl_set_folder_bynumber(folder, saved_folder_id);
212         fl_unfreeze_form(folder->form);
213
214         return num_folders;
215 #endif
216 }
217
218
219 // Returns the leaves making up a tabfolder.
220 vector<FL_FORM *> const leaves_in_tabfolder(FL_OBJECT * folder)
221 {
222         if (folder->objclass != FL_TABFOLDER)
223                 return vector<FL_FORM *>();
224
225         fl_freeze_form(folder->form);
226         int const saved_folder_id = fl_get_folder_number(folder);
227
228         int const size = get_tabfolder_numfolders(folder);
229         vector<FL_FORM *> leaves(size);
230
231         for (int i = 0; i < size; ++i) {
232                 fl_set_folder_bynumber(folder, i+1);
233                 leaves[i] = fl_get_folder(folder);
234         }
235
236         fl_set_folder_bynumber(folder, saved_folder_id);
237         fl_unfreeze_form(folder->form);
238
239         return leaves;
240 }
241
242
243 // The labels of each tab in the folder.
244 vector<string> const tab_names(FL_OBJECT * folder)
245 {
246         if (folder->objclass != FL_TABFOLDER)
247                 return vector<string>();
248
249         fl_freeze_form(folder->form);
250         int const saved_folder_id = fl_get_folder_number(folder);
251
252         int const size = get_tabfolder_numfolders(folder);
253         vector<string> names(size);
254
255         for (int i = 0; i < size; ++i) {
256                 fl_set_folder_bynumber(folder, i+1);
257
258                 char const * const name = fl_get_folder_name(folder);
259                 if (name)
260                         names[i] = name;
261         }
262
263         fl_set_folder_bynumber(folder, saved_folder_id);
264         fl_unfreeze_form(folder->form);
265
266         return names;
267 }
268
269 } // namespace anon