/**
* \file xforms_resize.C
- * Copyright 2000-2002 the LyX Team
- * Read the file COPYING
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
*
- * \author Angus Leeming, a.leeming@ic.ac.uk
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
*/
#include <config.h>
-#ifdef __GNUG__
-#pragma implementation
-#endif
#include "xforms_resize.h"
-#include "LString.h"
-#include <algorithm>
-#include <vector>
-
-using std::vector;
-
-namespace {
-
-// Returns the FL_OBJECT * of class FL_TABFOLDER if present in the form.
-// Else 0.
-FL_OBJECT * find_tabfolder(FL_FORM * form);
+#include <boost/assert.hpp>
-// Takes an FL_OBJECT * folder of class FL_TABFOLDER and calculates how much it
-// should be scaled to display all the tabs.
-// Returns 1 if the tabs are alll fully visible.
-// Nested tabfolders are not considered.
-double scale_to_fit_tabs(FL_OBJECT * folder);
-
-// Returns the leaves making up a tabfolder.
-vector<FL_FORM *> const leaves_in_tabfolder(FL_OBJECT * folder);
-
-// The labels of each tab in the folder.
-vector<string> const tab_names(FL_OBJECT * folder);
-
-} // namespace anon
-
-
-double scale_to_fit_tabs(FL_FORM * form)
-{
- if (!form)
- return 1;
-
- FL_OBJECT * folder = find_tabfolder(form);
- if (!folder)
- return 1;
-
- double scale = scale_to_fit_tabs(folder);
-
- vector<FL_FORM *> const leaves = leaves_in_tabfolder(folder);
- vector<FL_FORM *>::const_iterator it = leaves.begin();
- vector<FL_FORM *>::const_iterator end = leaves.end();
-
- for (; it != end; ++it) {
- folder = find_tabfolder(*it);
- if (folder)
- scale = std::max(scale, scale_to_fit_tabs(folder));
- }
-
- return scale;
-}
-
-
-void scale_form(FL_FORM * form, double scale_factor)
-{
- if (!form)
- return;
-
- fl_scale_form(form, scale_factor, 1);
-
- FL_OBJECT * folder = find_tabfolder(form);
- if (!folder)
- return;
-
- vector<FL_FORM *> const leaves = leaves_in_tabfolder(folder);
- vector<FL_FORM *>::const_iterator it = leaves.begin();
- vector<FL_FORM *>::const_iterator end = leaves.end();
-
- for (; it != end; ++it) {
- fl_scale_form(*it, scale_factor, 1);
- }
-}
+#include <algorithm> // std::max. Use FL_max in .c code...
+#include "lyx_forms.h"
namespace {
-FL_OBJECT * find_tabfolder(FL_FORM * form)
-{
- for (FL_OBJECT * ob = form->first; ob; ob = ob->next) {
- if (ob->objclass == FL_TABFOLDER)
- return ob;
- }
-
- return 0;
-}
-
-
-// Return the scaling factor needed to render all the tab labels.
-double scale_to_fit_tabs(FL_OBJECT * folder)
+/* This is hacked straight out of the xforms source.
+ It is fl_adjust_form_size without the last few lines that do the
+ adjusting.
+ */
+double get_scaling_factor(FL_FORM * form)
{
- if (folder->objclass != FL_TABFOLDER)
- return 1;
-
- // The problem here is that we can access the names of a tabfolder's
- // tabs directly (through fl_get_folder_name(folder)), but we
- // can't access directly the tabs themselves. Nonetheless, they are
- // made visible as buttons on the parent form, so we can obtain
- // the style info by a judicious camparison of names. This style info
- // (label font size, style) is needed to ascertain how much space
- // the label takes up.
-
- // The tabfolder makes the tabs (buttons) visible to the parent form,
- // so to identify them, we need their names.
- vector<string> const names = tab_names(folder);
- if (names.empty())
- return 1;
-
- FL_FORM * parent = folder->form;
- if (!parent)
- return 1;
-
- // Ascertain the style parameters of the tabs.
- int label_style = FL_BOLD_STYLE;
- int label_size = FL_NORMAL_SIZE;
- int box_width = 1;
- // Hard-coded within xforms' fl_create_tabfolder in tabfolder.c.
- int const tab_padding = 12;
-
- for (FL_OBJECT * ob = parent->first; ob; ob = ob->next) {
- if (!ob->label)
- continue;
-
- vector<string>::const_iterator it = names.begin();
- vector<string>::const_iterator end = names.end();
- it = std::find(it, end, ob->label);
-
- if (it == end)
- continue;
-
- label_style = ob->lstyle;
- label_size = ob->lsize;
-
- if (ob->boxtype == FL_UP_BOX || ob->boxtype == FL_DOWN_BOX)
- box_width = FL_abs(ob->bw);
-
- // achieved all we set out to achieve, so break.
- break;
+ FL_OBJECT *ob;
+ float xfactor, yfactor, max_factor, factor;
+ int sw, sh, osize;
+ float xm = 0.5f, ym = 0.5f;
+ int bw;
+
+// if (fl_no_connection)
+// return 1.0f;
+
+ max_factor = factor = 1.0f;
+ for (ob = form->first; ob; ob = ob->next)
+ {
+ if ((ob->align == FL_ALIGN_CENTER || (ob->align & FL_ALIGN_INSIDE) ||
+ ob->objclass == FL_INPUT) &&
+ !ob->is_child && *(ob->label) && ob->label[0] != '@' &&
+ ob->boxtype != FL_NO_BOX &&
+ (ob->boxtype != FL_FLAT_BOX || ob->objclass == FL_MENU))
+ {
+ fl_get_string_dimension(ob->lstyle, ob->lsize, ob->label,
+ strlen(ob->label), &sw, &sh);
+
+ bw = (ob->boxtype == FL_UP_BOX || ob->boxtype == FL_DOWN_BOX) ?
+ FL_abs(ob->bw) : 1;
+
+ if (ob->objclass == FL_BUTTON &&
+ (ob->type == FL_RETURN_BUTTON || ob->type == FL_MENU_BUTTON))
+ sw += (int)FL_min(0.6f * ob->h, 0.6f * ob->w) - 1;
+
+ if (ob->objclass == FL_BUTTON && ob->type == FL_LIGHTBUTTON)
+ sw += FL_LIGHTBUTTON_MINSIZE + 1;
+
+ if (sw <= (ob->w - 2 * (bw + xm)) && sh <= (ob->h - 2 * (bw + ym)))
+ continue;
+
+ if ((osize = ob->w - 2 * (int)(bw + xm)) <= 0)
+ osize = 1;
+ xfactor = (float) sw / (float)osize;
+
+ if ((osize = ob->h - 2 * (int)(bw + ym)) <= 0)
+ osize = 1;
+ yfactor = (float) sh / osize;
+
+ if (ob->objclass == FL_INPUT)
+ {
+ xfactor = 1.0f;
+ yfactor = (sh + 1.6f) / osize;
+ }
+
+ if ((factor = FL_max(xfactor, yfactor)) > max_factor)
+ {
+ max_factor = factor;
+ }
}
- // Hard coded in xforms' get_tabsize in tabfolder.c as
- // (2 + fudge) * box_width, where fudge is always 1.
- int const box_width_factor = 3 * box_width;
-
- // Loop over the names and calculate how much space is needed to display
- // them.
- int length = 0;
+ }
- vector<string>::const_iterator it = names.begin();
- vector<string>::const_iterator end = names.end();
+ if (max_factor <= 1.0f)
+ return 1.0f;
- for (; it != end; ++it) {
- int sw, sh;
+ max_factor = 0.01f * (int) (max_factor * 100.0f);
- fl_get_string_dimension(label_style, label_size,
- it->c_str(), int(it->size()),
- &sw, &sh);
-
- // This is the minimum width the object must be to contain
- // the label
- length += sw + tab_padding + box_width_factor;
- }
+ if (max_factor > 1.25f)
+ max_factor = 1.25f;
- // Compare this length to the width of the tabfolder
- double const scale = double(length) / double(folder->w);
- return std::max(double(1), scale);
+ return max_factor;
}
-// A nasty hack for older xforms versions
-int get_tabfolder_numfolders(FL_OBJECT * folder)
+double get_tabfolder_scale_to_fit(FL_OBJECT * folder)
{
-#if FL_VERSION > 0 || FL_REVISION > 88
- return fl_get_tabfolder_numfolders(folder);
-#else
- if (folder->objclass != FL_TABFOLDER)
- return 0;
+ BOOST_ASSERT(folder && folder->objclass == FL_TABFOLDER);
fl_freeze_form(folder->form);
int const saved_folder_id = fl_get_folder_number(folder);
- int num_folders = 0;
- FL_FORM const * old_leaf = 0;
- for (;;) {
- int const id = num_folders + 1;
- fl_set_folder_bynumber(folder, id);
- FL_FORM const * const leaf = fl_get_folder(folder);
- if (!leaf || leaf == old_leaf) {
- // unable to increment succesfully.
- break;
- }
- old_leaf = leaf;
- ++num_folders;
+ double factor = 1.0;
+ int const size = fl_get_tabfolder_numfolders(folder);
+ for (int i = 0; i < size; ++i) {
+ fl_set_folder_bynumber(folder, i+1);
+ FL_FORM * leaf = fl_get_folder(folder);
+ factor = std::max(factor, get_scale_to_fit(leaf));
}
fl_set_folder_bynumber(folder, saved_folder_id);
fl_unfreeze_form(folder->form);
- return num_folders;
-#endif
+ return factor;
}
-// Returns the leaves making up a tabfolder.
-vector<FL_FORM *> const leaves_in_tabfolder(FL_OBJECT * folder)
+void scale_tabfolder_horizontally(FL_OBJECT * folder, double factor)
{
- if (folder->objclass != FL_TABFOLDER)
- return vector<FL_FORM *>();
+ BOOST_ASSERT(folder && folder->objclass == FL_TABFOLDER);
fl_freeze_form(folder->form);
int const saved_folder_id = fl_get_folder_number(folder);
- int const size = get_tabfolder_numfolders(folder);
- vector<FL_FORM *> leaves(size);
-
+ int const size = fl_get_tabfolder_numfolders(folder);
for (int i = 0; i < size; ++i) {
fl_set_folder_bynumber(folder, i+1);
- leaves[i] = fl_get_folder(folder);
+ FL_FORM * leaf = fl_get_folder(folder);
+ scale_form_horizontally(leaf, factor);
}
fl_set_folder_bynumber(folder, saved_folder_id);
fl_unfreeze_form(folder->form);
-
- return leaves;
}
+} // namespace anon
+
-// The labels of each tab in the folder.
-vector<string> const tab_names(FL_OBJECT * folder)
+double get_scale_to_fit(FL_FORM * form)
{
- if (folder->objclass != FL_TABFOLDER)
- return vector<string>();
+ BOOST_ASSERT(form);
- fl_freeze_form(folder->form);
- int const saved_folder_id = fl_get_folder_number(folder);
+ double factor = get_scaling_factor(form);
+ for (FL_OBJECT * ob = form->first; ob; ob = ob->next) {
+ if (ob->objclass == FL_TABFOLDER)
+ factor = std::max(factor,
+ get_tabfolder_scale_to_fit(ob));
+ }
+ return factor;
+}
- int const size = get_tabfolder_numfolders(folder);
- vector<string> names(size);
- for (int i = 0; i < size; ++i) {
- fl_set_folder_bynumber(folder, i+1);
+void scale_form_horizontally(FL_FORM * form, double factor)
+{
+ BOOST_ASSERT(form);
- char const * const name = fl_get_folder_name(folder);
- if (name)
- names[i] = name;
- }
+ if (factor <= 1.0)
+ return;
- fl_set_folder_bynumber(folder, saved_folder_id);
- fl_unfreeze_form(folder->form);
+ fl_scale_form(form, factor, 1);
- return names;
+ for (FL_OBJECT * ob = form->first; ob; ob = ob->next) {
+ if (ob->objclass == FL_TABFOLDER)
+ scale_tabfolder_horizontally(ob, factor);
+ }
}
-
-} // namespace anon