Angus Leeming wrote:
> 
> Rob, here's an updated patch to replace what you have already. 
> It incorporates some bugfixes, your suggestions and most of 
> those made by Allan (off-list).
> 
> It also gives you a checkLyXLength() function for ... well, you 
> know.
> 
> I suspect that you'll be able to simplify those input() methods 
> considerably.

Thanks Angus!
 From now on, please don't send me patches pulled from your previous ones,
since I made modifications here and I'll have difficulties to merge them.

Attached a stripped version of my tree that only does the (glue)length
checking, and it's implemented into the Paragraph and Graphics dialogs.
(checkedwidgets.[Ch] are separately attached, 'cause I don't know how to
add them in the diff file).

There is a strange problem, that I tried to figure out, but couldn't; so
may be you can shine some light on it:
Paragraph works well. Enter an invalid length, click on [Cancel] and re-open
the dialog. Fine.
Graphics, on the other hand, is still buggy! Enter an invalid length, close
the dialog and reopen it: there's a valid length but colours are still red!
Its even worse: open the Graphics dialog, enter an invalid length, close the
dialog and then insert a new graphics inset, which pops up a fresh graphics
dialog: this graphics dialog also has widgets marked in red.

My problem is: I can't see where the Paragraph and Graphics differ.
Do you know?


Another thing I don't understand: I ran the debugger (gdb) with a breakpoint
at "CheckedGlueLength::check". Start LyX, do "File->New". You can mouse-click
anywhere on the canvas, no problem. Now open a dialog that uses the length check
and close it again; you'll have to continue several times at the breakpoint.
Now all of a sudden the leftmouse and middlemouse clicks on the canvas stop
at the breakpoint; the middlemouse click even more often than the leftmouse click.
What's going on here? Why does a canvas click need a length check?
It appears to me that the canvas click somehow is intertwined with the dialog stuff,
but only after a length-check-dialog has been used. Any idea what's wrong here?

Regards,
Rob.

Index: src/frontends/controllers/ButtonController.tmpl
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/frontends/controllers/ButtonController.tmpl,v
retrieving revision 1.5
diff -u -r1.5 ButtonController.tmpl
--- src/frontends/controllers/ButtonController.tmpl     2002/09/05 15:14:20     1.5
+++ src/frontends/controllers/ButtonController.tmpl     2002/10/03 08:01:02
@@ -29,17 +29,22 @@
 void GuiBC<Button, Widget>::refresh()
 {
        lyxerr[Debug::GUI] << "Calling BC refresh()" << std::endl; 
- 
+
+       bool const all_valid = checkWidgets();
+
        if (okay_) {
-               bool const enabled = bp().buttonStatus(ButtonPolicy::OKAY);
+               bool const enabled =
+                       all_valid && bp().buttonStatus(ButtonPolicy::OKAY);
                setButtonEnabled(okay_, enabled);
        }
        if (apply_) {
-               bool const enabled = bp().buttonStatus(ButtonPolicy::APPLY);
+               bool const enabled = 
+                       all_valid && bp().buttonStatus(ButtonPolicy::APPLY);
                setButtonEnabled(apply_, enabled);
        }
        if (restore_) {
-               bool const enabled = bp().buttonStatus(ButtonPolicy::RESTORE);
+               bool const enabled = 
+                       all_valid && bp().buttonStatus(ButtonPolicy::RESTORE);
                setButtonEnabled(restore_, enabled);
        }
        if (cancel_) {
Index: src/frontends/controllers/ButtonControllerBase.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/frontends/controllers/ButtonControllerBase.C,v
retrieving revision 1.9
diff -u -r1.9 ButtonControllerBase.C
--- src/frontends/controllers/ButtonControllerBase.C    2002/09/05 15:14:20     1.9
+++ src/frontends/controllers/ButtonControllerBase.C    2002/10/03 08:01:03
@@ -18,6 +18,10 @@
 #include "debug.h"
 
 
+CheckedWidget::~CheckedWidget()
+{}
+
+
 ButtonControllerBase::ButtonControllerBase(string const & cancel,
                                           string const & close)
        : cancel_label_(cancel), close_label_(close)
@@ -97,3 +101,29 @@
 {
        readOnly(false);
 }
+
+
+void ButtonControllerBase::addCheckedWidget(CheckedWidget * ptr)
+{
+       if (!ptr)
+               return;
+       checked_widgets.push_back(checked_widget_ptr(ptr));
+}
+
+
+bool ButtonControllerBase::checkWidgets()
+{
+       checked_widget_list::const_iterator it  = checked_widgets.begin();
+       checked_widget_list::const_iterator end = checked_widgets.end();
+
+       while (it != end) {
+               if ((*it)->check())
+                       ++it;
+               else
+                       return false;
+       }
+
+       // all are valid!
+       return true;
+}
+
Index: src/frontends/controllers/ButtonControllerBase.h
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/frontends/controllers/ButtonControllerBase.h,v
retrieving revision 1.9
diff -u -r1.9 ButtonControllerBase.h
--- src/frontends/controllers/ButtonControllerBase.h    2002/09/05 15:14:20     1.9
+++ src/frontends/controllers/ButtonControllerBase.h    2002/10/03 08:01:03
@@ -19,6 +19,21 @@
 #include "ButtonPolicies.h"
 #include "LString.h"
 
+#include <boost/shared_ptr.hpp>
+#include <list>
+
+struct CheckedWidget {
+       ///
+       virtual ~CheckedWidget();
+
+       /** Returns true if the widget is in a valid state.
+       *  Might also change the visual appearance of the widget,
+       *  to reflect this state.
+       */
+       virtual bool check() = 0;
+};
+
+
 /** Abstract base class for a ButtonController
 
  * Controls the activation of the OK, Apply and Cancel buttons.
@@ -70,12 +85,23 @@
        void valid(bool = true);
        ///
        void invalid();
+       ///
+       void addCheckedWidget(CheckedWidget * ptr);
 
 protected:
        ///
        string cancel_label_;
        ///
        string close_label_;
+       ///
+       bool checkWidgets();
+
+private:
+       ///
+       typedef boost::shared_ptr<CheckedWidget> checked_widget_ptr;
+       typedef std::list<checked_widget_ptr> checked_widget_list;
+       ///
+       checked_widget_list checked_widgets;
 };
 
 #endif // BUTTONCONTROLLERBASE_H
Index: src/frontends/controllers/ControlDialog.tmpl
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/frontends/controllers/ControlDialog.tmpl,v
retrieving revision 1.8
diff -u -r1.8 ControlDialog.tmpl
--- src/frontends/controllers/ControlDialog.tmpl        2002/09/05 15:14:21     1.8
+++ src/frontends/controllers/ControlDialog.tmpl        2002/10/03 08:01:04
@@ -45,6 +45,9 @@
 
        bc().readOnly(bufferIsReadonly());
        view().show();
+
+       // The widgets may not be valid, so refresh the button controller
+       bc().refresh();
 }
 
 template <class Base>
@@ -61,6 +64,9 @@
 
        bc().readOnly(bufferIsReadonly());
        view().update();
+
+       // The widgets may not be valid, so refresh the button controller
+       bc().refresh();
 }
 
 template <class Base>
Index: src/frontends/xforms/FormGraphics.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/frontends/xforms/FormGraphics.C,v
retrieving revision 1.85
diff -u -r1.85 FormGraphics.C
--- src/frontends/xforms/FormGraphics.C 2002/09/12 08:44:23     1.85
+++ src/frontends/xforms/FormGraphics.C 2002/10/03 08:01:16
@@ -25,6 +25,7 @@
 #include "xforms_helpers.h"
 #include "helper_funcs.h"
 #include "input_validators.h"
+#include "checkedwidgets.h"
 #include "debug.h" // for lyxerr
 #include "support/lstrings.h"  // for strToDbl & tostr
 #include "support/filetools.h"  // for MakeAbsPath etc
@@ -87,6 +88,12 @@
        // the file section
        file_.reset(build_graphics_file(this));
 
+       // check validity of "length + unit" input
+       bc().addCheckedWidget(
+               new CheckedGlueLength(file_->input_width));
+       bc().addCheckedWidget(
+               new CheckedGlueLength(file_->input_height));
+
        fl_set_input_return (file_->input_filename, FL_RETURN_CHANGED);
        fl_set_input_return (file_->input_lyxscale, FL_RETURN_CHANGED);
        fl_set_input_return (file_->input_width, FL_RETURN_CHANGED);
@@ -419,6 +426,8 @@
        if (igp.filename.empty()) {
                fl_set_folder(dialog_->tabfolder, file_->form);
        }
+       
+       input(0,0);
 }
 
 
Index: src/frontends/xforms/FormParagraph.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/frontends/xforms/FormParagraph.C,v
retrieving revision 1.80
diff -u -r1.80 FormParagraph.C
--- src/frontends/xforms/FormParagraph.C        2002/09/05 15:14:22     1.80
+++ src/frontends/xforms/FormParagraph.C        2002/10/03 08:01:19
@@ -24,6 +24,7 @@
 #include "lyxrc.h" // to set the deafult length values
 #include "input_validators.h"
 #include "helper_funcs.h"
+#include "checkedwidgets.h"
 #include "gettext.h"
 #include "xformsBC.h"
 #include "layout.h" // LyXAlignment
@@ -52,6 +53,14 @@
        // Allow the base class to control messages
        setMessageWidget(dialog_->text_warning);
 
+       // check validity of "length + unit" input
+       bc().addCheckedWidget(
+               new CheckedGlueLength(dialog_->input_space_above,
+                               dialog_->choice_space_above));
+       bc().addCheckedWidget(
+               new CheckedGlueLength(dialog_->input_space_below,
+                               dialog_->choice_space_below));
+
        fl_addto_choice(dialog_->choice_space_above,
                        _(" None | Defskip | Smallskip "
                          "| Medskip | Bigskip | VFill | Length "));
@@ -427,6 +436,8 @@
        /* no indent */
        fl_set_button(dialog_->check_noindent,
                      controller().params().noindent());
+
+       input(0,0);
 }
 
 namespace {
/**
 * \file checkedwidgets.C
 * This file is part of LyX, the document processor.
 * Licence details can be found in the file COPYING.
 *
 * \author Angus Leeming
 *
 * Full author contact details are available in file CREDITS
 */

#include <config.h>

#ifdef __GNUG__
#pragma implementation
#endif

#include "checkedwidgets.h"
#include "xforms_helpers.h"
#include "lyxlength.h"
#include "lyxgluelength.h"
#include "support/LAssert.h"
#include "support/lstrings.h"
#include FORMS_H_LOCATION
#include "LString.h"

void setWidget(bool valid, FL_OBJECT * input, FL_OBJECT * label);


void addCheckedLyXLength(ButtonControllerBase & bc,
                         FL_OBJECT * input, FL_OBJECT * label)
{
        bc.addCheckedWidget(new CheckedLyXLength(input, label));
}


void addCheckedGlueLength(ButtonControllerBase & bc,
                          FL_OBJECT * input, FL_OBJECT * label)
{
        bc.addCheckedWidget(new CheckedGlueLength(input, label));
}


CheckedLyXLength::CheckedLyXLength(FL_OBJECT * input, FL_OBJECT * label)
        : input_(input), label_(label ? label : input)
{
        lyx::Assert(input && input->objclass == FL_INPUT);
}

bool CheckedLyXLength::check()
{
        string const str = input_->active ? getString(input_) : string();
        bool const valid =
                str.empty() || isStrDbl(str) || isValidLength(str);

        // set the color of label and input widget
        setWidget(valid, input_, label_);

        return valid;
}


CheckedGlueLength::CheckedGlueLength(FL_OBJECT * input, FL_OBJECT * label)
        : input_(input), label_(label ? label : input)
{
        lyx::Assert(input && input->objclass == FL_INPUT);
}

bool CheckedGlueLength::check()
{
        string const str = input_->active ? getString(input_) : string();
        bool const valid =
                str.empty() || isStrDbl(str) || isValidGlueLength(str);

        // set the color of label and input widget
        setWidget(valid, input_, label_);

        return valid;
}


void setWidget(bool valid, FL_OBJECT * input, FL_OBJECT * label)
{
        // set label color
        FL_COLOR const lcol = valid ? FL_LCOL : FL_RED;
        if (lcol != label->lcol) {
                fl_set_object_lcol(label, lcol);
                if (lcol != input->lcol) {
                        fl_set_object_lcol(input, lcol);
                }
        }

        // set background color of input widget
        FL_COLOR const icol1 = valid ? FL_INPUT_COL1 : FL_RED;
        FL_COLOR const icol2 = valid ? FL_INPUT_COL2 : FL_RED;
        if (icol1 != input->col1 || icol2 != input->col2) {
                fl_set_object_color(input, icol1, icol2);
        }       
}
// -*- C++ -*-
/**
 * \file checkedwidgets.h
 * This file is part of LyX, the document processor.
 * Licence details can be found in the file COPYING.
 *
 * \author Angus Leeming
 *
 * Full author contact details are available in file CREDITS
 */

#ifndef CHECKEDWIDGETS_H
#define CHECKEDWIDGETS_H

#ifdef __GNUG__
#pragma interface
#endif

#include "ButtonControllerBase.h"
#include "forms_fwd.h"

void addCheckedLyXLength(ButtonControllerBase & bc,
                        FL_OBJECT * input, FL_OBJECT * label = 0);

void addCheckedGlueLength(ButtonControllerBase & bc,
                        FL_OBJECT * input, FL_OBJECT * label = 0);

class CheckedLyXLength : public CheckedWidget {
public:
        /** The label widget's label will be turned red if input
         *  does not make a valid LyXLength.
         *  If label == 0, then the label of input will be used.
         */
        CheckedLyXLength(FL_OBJECT * input, FL_OBJECT * label = 0);

private:
        ///
        virtual bool check();

        ///
        FL_OBJECT * input_;
        FL_OBJECT * label_;
};


class CheckedGlueLength : public CheckedWidget {
public:
        /** The label widget's label will be turned red if input
         *  does not make a valid LyXGlueLength.
         *  If label == 0, then the label of input will be used.
         */
        CheckedGlueLength(FL_OBJECT * input, FL_OBJECT * label = 0);

private:
        ///
        virtual bool check();

        ///
        FL_OBJECT * input_;
        FL_OBJECT * label_;
};

#endif // CHECKEDWIDGETS_H

Reply via email to