2 * \file xforms_resize.C
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
8 * Full author contact details are available in file CREDITS
14 #pragma implementation
17 #include "xforms_resize.h"
22 #include FORMS_H_LOCATION
28 // Returns the FL_OBJECT * of class FL_TABFOLDER if present in the form.
30 FL_OBJECT * find_tabfolder(FL_FORM * form);
32 // Takes an FL_OBJECT * folder of class FL_TABFOLDER and calculates how much it
33 // should be scaled to display all the tabs.
34 // Returns 1 if the tabs are alll fully visible.
35 // Nested tabfolders are not considered.
36 double scale_to_fit_tabs(FL_OBJECT * folder);
38 // Returns the leaves making up a tabfolder.
39 vector<FL_FORM *> const leaves_in_tabfolder(FL_OBJECT * folder);
41 // The labels of each tab in the folder.
42 vector<string> const tab_names(FL_OBJECT * folder);
47 double scale_to_fit_tabs(FL_FORM * form)
52 FL_OBJECT * folder = find_tabfolder(form);
56 double scale = scale_to_fit_tabs(folder);
58 vector<FL_FORM *> const leaves = leaves_in_tabfolder(folder);
59 vector<FL_FORM *>::const_iterator it = leaves.begin();
60 vector<FL_FORM *>::const_iterator end = leaves.end();
62 for (; it != end; ++it) {
63 folder = find_tabfolder(*it);
65 scale = std::max(scale, scale_to_fit_tabs(folder));
72 void scale_form(FL_FORM * form, double scale_factor)
77 fl_scale_form(form, scale_factor, 1);
79 FL_OBJECT * folder = find_tabfolder(form);
83 vector<FL_FORM *> const leaves = leaves_in_tabfolder(folder);
84 vector<FL_FORM *>::const_iterator it = leaves.begin();
85 vector<FL_FORM *>::const_iterator end = leaves.end();
87 for (; it != end; ++it) {
88 fl_scale_form(*it, scale_factor, 1);
95 FL_OBJECT * find_tabfolder(FL_FORM * form)
97 for (FL_OBJECT * ob = form->first; ob; ob = ob->next) {
98 if (ob->objclass == FL_TABFOLDER)
106 // Return the scaling factor needed to render all the tab labels.
107 double scale_to_fit_tabs(FL_OBJECT * folder)
109 if (folder->objclass != FL_TABFOLDER)
112 // The problem here is that we can access the names of a tabfolder's
113 // tabs directly (through fl_get_folder_name(folder)), but we
114 // can't access directly the tabs themselves. Nonetheless, they are
115 // made visible as buttons on the parent form, so we can obtain
116 // the style info by a judicious camparison of names. This style info
117 // (label font size, style) is needed to ascertain how much space
118 // the label takes up.
120 // The tabfolder makes the tabs (buttons) visible to the parent form,
121 // so to identify them, we need their names.
122 vector<string> const names = tab_names(folder);
126 FL_FORM * parent = folder->form;
130 // Ascertain the style parameters of the tabs.
131 int label_style = FL_BOLD_STYLE;
132 int label_size = FL_NORMAL_SIZE;
134 // Hard-coded within xforms' fl_create_tabfolder in tabfolder.c.
135 int const tab_padding = 12;
137 for (FL_OBJECT * ob = parent->first; ob; ob = ob->next) {
141 vector<string>::const_iterator it = names.begin();
142 vector<string>::const_iterator end = names.end();
143 it = std::find(it, end, ob->label);
148 label_style = ob->lstyle;
149 label_size = ob->lsize;
151 if (ob->boxtype == FL_UP_BOX || ob->boxtype == FL_DOWN_BOX)
152 box_width = FL_abs(ob->bw);
154 // achieved all we set out to achieve, so break.
157 // Hard coded in xforms' get_tabsize in tabfolder.c as
158 // (2 + fudge) * box_width, where fudge is always 1.
159 int const box_width_factor = 3 * box_width;
161 // Loop over the names and calculate how much space is needed to display
165 vector<string>::const_iterator it = names.begin();
166 vector<string>::const_iterator end = names.end();
168 for (; it != end; ++it) {
171 fl_get_string_dimension(label_style, label_size,
172 it->c_str(), int(it->size()),
175 // This is the minimum width the object must be to contain
177 length += sw + tab_padding + box_width_factor;
180 // Compare this length to the width of the tabfolder
181 double const scale = double(length) / double(folder->w);
182 return std::max(double(1), scale);
186 // A nasty hack for older xforms versions
187 int get_tabfolder_numfolders(FL_OBJECT * folder)
189 #if FL_VERSION > 0 || FL_REVISION > 88
190 return fl_get_tabfolder_numfolders(folder);
192 if (folder->objclass != FL_TABFOLDER)
195 fl_freeze_form(folder->form);
196 int const saved_folder_id = fl_get_folder_number(folder);
199 FL_FORM const * old_leaf = 0;
201 int const id = num_folders + 1;
202 fl_set_folder_bynumber(folder, id);
203 FL_FORM const * const leaf = fl_get_folder(folder);
204 if (!leaf || leaf == old_leaf) {
205 // unable to increment succesfully.
212 fl_set_folder_bynumber(folder, saved_folder_id);
213 fl_unfreeze_form(folder->form);
220 // Returns the leaves making up a tabfolder.
221 vector<FL_FORM *> const leaves_in_tabfolder(FL_OBJECT * folder)
223 if (folder->objclass != FL_TABFOLDER)
224 return vector<FL_FORM *>();
226 fl_freeze_form(folder->form);
227 int const saved_folder_id = fl_get_folder_number(folder);
229 int const size = get_tabfolder_numfolders(folder);
230 vector<FL_FORM *> leaves(size);
232 for (int i = 0; i < size; ++i) {
233 fl_set_folder_bynumber(folder, i+1);
234 leaves[i] = fl_get_folder(folder);
237 fl_set_folder_bynumber(folder, saved_folder_id);
238 fl_unfreeze_form(folder->form);
244 // The labels of each tab in the folder.
245 vector<string> const tab_names(FL_OBJECT * folder)
247 if (folder->objclass != FL_TABFOLDER)
248 return vector<string>();
250 fl_freeze_form(folder->form);
251 int const saved_folder_id = fl_get_folder_number(folder);
253 int const size = get_tabfolder_numfolders(folder);
254 vector<string> names(size);
256 for (int i = 0; i < size; ++i) {
257 fl_set_folder_bynumber(folder, i+1);
259 char const * const name = fl_get_folder_name(folder);
264 fl_set_folder_bynumber(folder, saved_folder_id);
265 fl_unfreeze_form(folder->form);