2 * \file xforms_resize.C
3 * Copyright 2000-2002 the LyX Team
4 * Read the file COPYING
6 * \author Angus Leeming, a.leeming@ic.ac.uk
12 #pragma implementation
15 #include "xforms_resize.h"
25 // Returns the FL_OBJECT * of class FL_TABFOLDER if present in the form.
27 FL_OBJECT * find_tabfolder(FL_FORM * form);
29 // Takes an FL_OBJECT * folder of class FL_TABFOLDER and calculates how much it
30 // should be scaled to display all the tabs.
31 // Returns 1 if the tabs are alll fully visible.
32 // Nested tabfolders are not considered.
33 double scale_to_fit_tabs(FL_OBJECT * folder);
35 // Returns the leaves making up a tabfolder.
36 vector<FL_FORM *> const leaves_in_tabfolder(FL_OBJECT * folder);
38 // The labels of each tab in the folder.
39 vector<string> const tab_names(FL_OBJECT * folder);
44 double scale_to_fit_tabs(FL_FORM * form)
49 FL_OBJECT * folder = find_tabfolder(form);
53 double scale = scale_to_fit_tabs(folder);
55 vector<FL_FORM *> const leaves = leaves_in_tabfolder(folder);
56 vector<FL_FORM *>::const_iterator it = leaves.begin();
57 vector<FL_FORM *>::const_iterator end = leaves.end();
59 for (; it != end; ++it) {
60 folder = find_tabfolder(*it);
62 scale = std::max(scale, scale_to_fit_tabs(folder));
69 void scale_form(FL_FORM * form, double scale_factor)
74 fl_scale_form(form, scale_factor, 1);
76 FL_OBJECT * folder = find_tabfolder(form);
80 vector<FL_FORM *> const leaves = leaves_in_tabfolder(folder);
81 vector<FL_FORM *>::const_iterator it = leaves.begin();
82 vector<FL_FORM *>::const_iterator end = leaves.end();
84 for (; it != end; ++it) {
85 fl_scale_form(*it, scale_factor, 1);
92 FL_OBJECT * find_tabfolder(FL_FORM * form)
94 for (FL_OBJECT * ob = form->first; ob; ob = ob->next) {
95 if (ob->objclass == FL_TABFOLDER)
103 // Return the scaling factor needed to render all the tab labels.
104 double scale_to_fit_tabs(FL_OBJECT * folder)
106 if (folder->objclass != FL_TABFOLDER)
109 // The problem here is that we can access the names of a tabfolder's
110 // tabs directly (through fl_get_folder_name(folder)), but we
111 // can't access directly the tabs themselves. Nonetheless, they are
112 // made visible as buttons on the parent form, so we can obtain
113 // the style info by a judicious camparison of names. This style info
114 // (label font size, style) is needed to ascertain how much space
115 // the label takes up.
117 // The tabfolder makes the tabs (buttons) visible to the parent form,
118 // so to identify them, we need their names.
119 vector<string> const names = tab_names(folder);
123 FL_FORM * parent = folder->form;
127 // Ascertain the style parameters of the tabs.
128 int label_style = FL_BOLD_STYLE;
129 int label_size = FL_NORMAL_SIZE;
131 // Hard-coded within xforms' fl_create_tabfolder in tabfolder.c.
132 int const tab_padding = 12;
134 for (FL_OBJECT * ob = parent->first; ob; ob = ob->next) {
138 vector<string>::const_iterator it = names.begin();
139 vector<string>::const_iterator end = names.end();
140 it = std::find(it, end, ob->label);
145 label_style = ob->lstyle;
146 label_size = ob->lsize;
148 if (ob->boxtype == FL_UP_BOX || ob->boxtype == FL_DOWN_BOX)
149 box_width = FL_abs(ob->bw);
151 // achieved all we set out to achieve, so break.
154 // Hard coded in xforms' get_tabsize in tabfolder.c as
155 // (2 + fudge) * box_width, where fudge is always 1.
156 int const box_width_factor = 3 * box_width;
158 // Loop over the names and calculate how much space is needed to display
162 vector<string>::const_iterator it = names.begin();
163 vector<string>::const_iterator end = names.end();
165 for (; it != end; ++it) {
168 fl_get_string_dimension(label_style, label_size,
169 it->c_str(), int(it->size()),
172 // This is the minimum width the object must be to contain
174 length += sw + tab_padding + box_width_factor;
177 // Compare this length to the width of the tabfolder
178 double const scale = double(length) / double(folder->w);
179 return std::max(double(1), scale);
183 // A nasty hack for older xforms versions
184 int get_tabfolder_numfolders(FL_OBJECT * folder)
187 return fl_get_tabfolder_numfolders(folder);
189 if (folder->objclass != FL_TABFOLDER)
192 fl_freeze_form(folder->form);
193 int const saved_folder_id = fl_get_folder_number(folder);
196 FL_FORM const * old_leaf = 0;
198 int const id = num_folders + 1;
199 fl_set_folder_bynumber(folder, id);
200 FL_FORM const * const leaf = fl_get_folder(folder);
201 if (!leaf || leaf == old_leaf) {
202 // unable to increment succesfully.
209 fl_set_folder_bynumber(folder, saved_folder_id);
210 fl_unfreeze_form(folder->form);
217 // Returns the leaves making up a tabfolder.
218 vector<FL_FORM *> const leaves_in_tabfolder(FL_OBJECT * folder)
220 if (folder->objclass != FL_TABFOLDER)
221 return vector<FL_FORM *>();
223 fl_freeze_form(folder->form);
224 int const saved_folder_id = fl_get_folder_number(folder);
226 int const size = get_tabfolder_numfolders(folder);
227 vector<FL_FORM *> leaves(size);
229 for (int i = 0; i < size; ++i) {
230 fl_set_folder_bynumber(folder, i+1);
231 leaves[i] = fl_get_folder(folder);
234 fl_set_folder_bynumber(folder, saved_folder_id);
235 fl_unfreeze_form(folder->form);
241 // The labels of each tab in the folder.
242 vector<string> const tab_names(FL_OBJECT * folder)
244 if (folder->objclass != FL_TABFOLDER)
245 return vector<string>();
247 fl_freeze_form(folder->form);
248 int const saved_folder_id = fl_get_folder_number(folder);
250 int const size = get_tabfolder_numfolders(folder);
251 vector<string> names(size);
253 for (int i = 0; i < size; ++i) {
254 fl_set_folder_bynumber(folder, i+1);
256 char const * const name = fl_get_folder_name(folder);
261 fl_set_folder_bynumber(folder, saved_folder_id);
262 fl_unfreeze_form(folder->form);