#ifndef __BLOP_GROB_H__ #define __BLOP_GROB_H__ #include "length.h" #include "terminal.h" #include <vector> namespace blop { class pad; class container; /* grob == GRaphical OBject This is meant to be the base class for all graphical objects */ class grob { friend class container; private: container *parent_; std::string name_; bool autodel_; protected: virtual bool parent(container *p); // When a grob is added into a container, the container // calls this function to notify the grob about being // added into a container. Derived classes can overload // this function to make additional bookkeeping, but // they should always call grob::parent(...) as well. // If the function returns false (as in the case of // the 'canvas'), it means that this object can not // be added into a container, and the container will not // store a reference to this object int print_me_; // indicates status: // 0 ==> do not print this object, do not specialize its lengths // 1 ==> do not print, but calculate lengths // 2 ==> print static length &default_x_unit_(); static length &default_y_unit_(); static bool default_use_parent_x_unit_, default_use_parent_y_unit_; length x_unit_, y_unit_, parent_cwidth_, parent_cheight_; bool modified_; var layer_; public: string name() const {return name_;} void name(const string &s) {name_ = s;} virtual bool modified() const { return modified_; } virtual void modified(bool f) { modified_ = f; } // ---------- Returns the parent of this grob ------------------------------------ virtual container *parent() { return parent_; } virtual const container *parent() const { return parent_; } static void default_x_unit(length l); static void default_y_unit(length l); static void default_unit(length); enum { use_parent = 100 }; static void default_x_unit(int); static void default_y_unit(int); static void default_unit(int); length x_unit(); length y_unit(); grob &x_unit(length); grob &x_unit(int); grob &y_unit(length); grob &y_unit(int); grob &unit(length); grob &unit(int); // -------------------------------------------------------------------------------- // This member function should make all necessary preparations, // which are needed for the object to be drawn (axes have to // calculate their ranges, lengths have to be registered, etc) // The different graphical objects, depending on their type, // will need different sets of lengths in order to be // drawn onto a terminal. These lengths will have to be // specialized (see length.h). In order to specialize all // needed lengths, they should be registered (length::register_me()) // This member function should call length::register_me() on // the lengths, which are needed for it to be drawn. virtual void prepare_for_draw() = 0; // -------------------------------------------------------------------------------- // grobs can be contained in containers. Sine grobs can be // created as automatic variables also (when their destructor // is automatically called when they scope expires), containers // do not deallocate these objects when they are cleared. // However, when creating grobs dynamically (operator new), // one's task is easier if containers deallocate the // objects. // Containers (when deleted or cleared) will deallocate // those grobs in them, which have autodel=true // autodel is false by default grob &autodel(bool b) { autodel_ = b; return *this; } bool autodel() const { return autodel_; } // ---------- change layer -------------------------------------------------------- virtual grob &layer(const var &l) { layer_ = l; return *this; } virtual const var &layer() const { return layer_; } grob(); // -------------------------------------------------------------------------------- // The destructor scans all existing containers (every container // is registered behind the scenes), and removes the currently // destroyed grob from all containers, so you never have to worry, // that a container holds a reference to an unexisting grob. virtual ~grob(); virtual void print(terminal *) = 0; // -------------------------------------------------------------------------------- // switch on or off the object (that is, the object will // be printed or not) virtual void on () {print_me_ = 2;} // object will be printed virtual void invisible() {print_me_ = 1;} // object not printed, but lengths calculated virtual void off() {print_me_ = 0;} // not printed, no lengths are calculated virtual int visibility() const { return print_me_; } virtual void print_hierarchy(int level=0); }; } #endif