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