# To subscribers of the xforms list from "T.C. Zhao" <tc_zhao@yahoo.com> :
There is no reason for not having access functions to
the tabs themselves other than oversight. Actually
on the back of my mind when coding the tabfolder, I was thinking
about access functions (so users may turn the tab, a regular button,
into a pixmap button), but mistakenly thought that
creation functons return the tab so the application
knows about it. Of course, this makes retro-change
hard to do as you've found out.
Maybe Steve can add the access function ? It should be
relatively straight forward.
-TC
--- Angus Leeming <a.leeming@ic.ac.uk> wrote:
> Hi, we've used tabfolders in a number of dialogs in LyX and are pretty
> happy
> with the results. However, they aren't exactly easy to code with. Here's an
>
> example of unnecessarily difficult code:
>
> The tabs identifying each leaf of the folder have a label whose length is
> unknown when the dialog is designed. (Because these labels are translated
> to
> eg German). Consequently, the tabs can become wider than the folder and are
>
> then, rather elegantly, chopped off by xforms.
>
> That's all well and good, but the obvious "correct" fix is to ascertain how
>
> much space the tabs require to be displayed fully and to then scle the
> dialog
> appropriately. Here's where I have to invent convoluted code.
>
> The tabfolders have accessor functions returning the names on the tabs
> char * fl_get_folder_name(FL_OBJECT * folder);
> and the leaves of the folder
> FL_FORM * fl_get_folder(FL_OBJECT * folder);
>
> but it appears that the tab buttons themselves have been made deliberately
> hard to get at. There is no
> FL_OBJECT * fl_get_folder_tab(FL_OBJECT * folder);
>
> This is a shame!
>
> The tabs CAN be found, but in a convoluted fashion, as they are visible to
> the folder's parent form, folder->form. A comparison of ob->label with
> fl_get_folder_name(folder) allows me to ascertain which objects are tabs
> and
> hence allows me to work out the space taken up by the tab. All very
> complicated.
>
> I attach the code that does all this so you can see what I'm taking about.
>
> Was there a reason for making the tab so hard to get at?
> If not, can we have an accessor function?
>
> Best regards,
> Angus
> > // -*- C++ -*-
> /**
> * \file xforms_resize.h
> * Copyright 2000-2002 the LyX Team
> * Read the file COPYING
> *
> * \author Angus Leeming, a.leeming@ic.ac.uk
> */
>
> #ifndef XFORMS_RESIZE_H
> #define XFORMS_RESIZE_H
>
> #ifdef __GNUG__
> #pragma interface
> #endif
>
> #include FORMS_H_LOCATION
>
> /** If the form contains a tabfolder, then by how much should the form be
> scaled (enlarged only) to render the tabs (buttons) visible?
>
> Returns 1 if the form does not contain a tabfolder.
>
> This routine works for two levels of nested tabfolders. (I.e., is
> sufficient
> for our current needs.)
> */
> double scale_to_fit_tabs(FL_FORM * form);
>
> /** A wrapper for fl_scale_form(form, scale, 1) that scales the parent form
> horizontally, but also scales the leaves (FL_FORMs) of any nested
> tabfolder, should one exist.
> */
> void scale_form(FL_FORM * form, double scale_factor);
>
> #endif // XFORMS_RESIZE_H
> > /**
> * \file xforms_resize.C
> * Copyright 2000-2002 the LyX Team
> * Read the file COPYING
> *
> * \author Angus Leeming, a.leeming@ic.ac.uk
> */
>
> #include <config.h>
>
> #ifdef __GNUG__
> #pragma implementation
> #endif
>
> #include "xforms_resize.h"
>
> #include <string>
> #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);
>
> // 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)
> continue;
> double folder_scale = scale_to_fit_tabs(folder);
> scale = std::max(scale, folder_scale);
> }
>
> 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);
> }
> }
>
>
> 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)
> {
> 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;
> }
> // 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();
>
> for (; it != end; ++it) {
> int sw, sh;
>
> 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;
> }
>
> // Compare this length to the width of the tabfolder
> double scale = double(length) / double(folder->w);
> return std::max(double(1), scale);
> }
>
>
> // Returns the leaves making up a tabfolder.
> vector<FL_FORM *> const leaves_in_tabfolder(FL_OBJECT * folder)
> {
> if (folder->objclass != FL_TABFOLDER)
> return vector<FL_FORM *>();
>
> fl_freeze_form(folder->form);
> int const folder_id = fl_get_folder_number(folder);
>
> int const size = fl_get_tabfolder_numfolders(folder);
> vector<FL_FORM *> leaves(size);
>
> for (int i = 0; i < size; ++i) {
> fl_set_folder_bynumber(folder, i+1);
> leaves[i] = fl_get_folder(folder);
> }
>
=== message truncated ===
__________________________________________________
Do You Yahoo!?
Yahoo! Shopping - Mother's Day is May 12th!
http://shopping.yahoo.com
_________________________________________________
To unsubscribe, send the message "unsubscribe" to
xforms-request@bob.usuhs.mil or see
http://bob.usuhs.mil/mailserv/xforms.html
XForms Home Page: http://world.std.com/~xforms
List Archive: http://bob.usuhs.mil/mailserv/list-archives/
This archive was generated by hypermail 2b29 : Thu May 09 2002 - 12:30:22 EDT