Re: XForms: scaling tabfolders to display ALL the tabs

From: T.C. Zhao (tc_zhao@yahoo.com)
Date: Thu May 09 2002 - 12:27:51 EDT

  • Next message: Peter S Galbraith: "Re: XForms: XForms version 1.0 and administrivia"

    # 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