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;
}

Reply via email to