I think that the following hierarchy fullfills all our needs with a minimum
amout of code. Question is, are you all happy with it!
Angus
class Inset {
public:
enum EDITABLE {
///
NOT_EDITABLE = 0,
///
IS_EDITABLE,
///
HIGHLY_EDITABLE
};
virtual int ascent() const = 0;
virtual int descent() const = 0;
virtual int width() const = 0;
virtual void draw() const = 0;
virtual EDITABLE editable() const = 0;
/// Lots of other methods exemplified by:
virtual void foo() const = 0;
};
class EditableButton {
public:
/// Instantiate the ascent, descent, width, draw methods here
virtual int ascent() const;
virtual int descent() const;
virtual int width() const;
virtual void draw() const;
virtual EDITABLE editable() const { return IS_EDITABLE; }
/// The daughter class must instantiate this
virtual string const getScreenLabel() const = 0;
};
class NonEditableButton {
public:
/// Instantiate the ascent, descent, width, draw methods here
virtual int ascent() const;
virtual int descent() const;
virtual int width() const;
virtual void draw() const;
virtual EDITABLE editable() const { return NOT_EDITABLE; }
/// The daughter class must instantiate this
virtual string const getScreenLabel() const = 0;
};
template <class Button, class Base>
class InsetButton: public Button, public Base {
public:
virtual int ascent() const { return button.ascent(); }
virtual int descent() const { return button.descent(); }
virtual int width() const { return button.width(); }
virtual void draw() const { button.draw(); }
virtual EDITABLE editable() const { return button.editable(); }
private:
Button button;
};
class InsetExternal : public InsetButton<EditableButton, Inset> {
public:
virtual string const getScreenLabel() const;
};
class InsetFloatList : public InsetButton<EditableButton, Inset> {
public:
virtual string const getScreenLabel() const;
};
class InsetInclude : public InsetButton<EditableButton, Inset> {
public:
virtual string const getScreenLabel() const;
};
// No longer derives from InsetButton. Leave this to the daughter
// classes as they are the ones deciding whether they're EDITABLE or not
class InsetCommand : public Inset {
public:
virtual string const getScreenLabel() const;
};
class InsetCitation : public InsetButton<EditableButton, InsetCommand> {
public:
virtual string const getScreenLabel() const;
};
class InsetIndex : public InsetButton<EditableButton, InsetCommand> {
public:
virtual string const getScreenLabel() const;
};
class InsetPrintIndex : public InsetButton<NonEditableButton, InsetCommand> {
public:
virtual string const getScreenLabel() const;
};
class InsetCollapsable : public UpdatableInset {
public:
/// Why public?
InsetText inset;
virtual int ascent() const { return button.ascent(); }
virtual int descent() const
{
if (collapsed_)
return button.descent();
return button.descent()
+ inset.descent()
+ inset.ascent()
+ TEXT_TO_BOTTOM_OFFSET;
}
virtual int width() const;
{
int widthButton = button.width();
if (collapsed_)
return widthButton;
return (inset.width(bv, font) > widthButton) ?
inset.width(bv, font) : widthButton;
}
/// etc, etc, etc
virtual void draw() const;
private:
Button button;
}