Skip to content

Library hg_interact

ta2la edited this page May 24, 2020 · 28 revisions

GObject System

GObject

The library provides interactivity between the user and the graphics objects. The graphics object itself is represented GObject class. Class GObject is a unique representation of a graphics object throughout the application. A strict recommendation is to use references and not GObject clones. Use GObject to express whatever you want by inheriting it: symbol, line, circle, car, tree, matrix, color-table ... The thing you want is created by assembling GObject s. In the following image is GObject the line connector and the text:

image

The GObject has a method virtual void display(EntityList&, RefCol*). You must overwrite this method to enable its displaying. The GObject handles the selection state of the object. You can call GObject::isSelectedSet() method to handle its selection state and overwrite the method virtual EIdentified identifiedByPoint( const Canvas&, const Point2F& ) to enable the selection the object by clicking.

Ref

Ref is a reference to GObject. There can be as many references as you want and each GObject has evidence about all its references. All the object references are destroyed together with the GObject itself. Ref solves the multi-display possibility of single GObject.

The object has two basic methods:

  • virtual void repaint() - repaints the object. In the basic implementation it uses GObject::display method but it is possible to overwrite the method for another appearance of the object.

  • bool identifiedByPoint( const Canvas&, const Point2F&) identifies the object in its specific appearance. In its basic implementation, it uses the entities generated by repaint().

RefCol

RefCol is collection of Ref s. It is possible to add a reference to the object in GObject using the method virtual bool add(GObject*) . But this is not the preferred approach. There is possible to associate object Filter with the object RefCol and then the content of a RefCol is handled automatically. If a GObject is created, then it is automatically added in RefCol if it passes the Filter. The same behavior is performed on GObject change.

RefCol specialization is object Scene. This object translates GObject s stored in RefCol in list of graphical entities in EntityPack. Entities are objects which can be directly rendered. Scene is updated on each change in RefCol.

You can use the same approach as used in object Scene to translate GObject s in any displayable format ( form, HTML, ... ).

Filter

Filter has the only method virtual bool pass(TcObject*). It checks if the GObject belongs to the given category or not. Using specializations of this object you can check if GObject belongs to a given file, layer, floor, project or whatever. It is used mainly for handling the content of RefCol.

FilterCol TODO

GObjectPool

GObjectPool registers all instances of GObject in a single instance GObjectPool::instance(). Don't worry about it. Each GObject is registered automatically in this one instance of the GObjectPool.

What ought to be added in GObjectPool manually is RefCol using the method addRefCol(RefCol*). Otherwise, the RefCol will not work automatically, as it is expected, its display will not be redrawn if RefCol will not be registered.

There is one collection pre-created in GObjectPool. It is the collection RefColSelection& selected(). It contains all the selected GObject s. It is also a good example of cooperation of the Filter and RefCol:

class FilterSelection : public Filter {
   public:
   virtual bool pass(TcObject* object) {
      GObject* objectDisplay = dynamic_cast<GObject*>(object);
      if ( objectDisplay == NULL ) return false;
      return objectDisplay->isSelected();
   }
}

class RefColSelection : public RefCol {
   public:
   RefColSelection() : RefCol(new FilterSelection()) {};
}

UpdateLock

The typical scenario is to change some GObject s and do not care how and where they will be updated on its display. On the other side, there is not desirable to update displays on each partial GObject change. Just UpdateLock, do some changes with GObject s and then all the refresh will be done on last existing UpdateLock destruction. The UpdateLock objects can be used repeatedly on the function call stack. Only the last UpdateLock instance destruction has the effect.

GObject specialization - TODO

class CadLine : public GObject {
public:
    CadLine( const Point2Col<double>& points, GFile* parent );
    ~CadLine(void);
//<METHODS>
//===================================================================
//<OVERRIDES>
    virtual void display(EntityList& list, RefCol* scene);
    virtual bool loadFromStored(StoredItem* item, GFile* file);
    virtual void saveToStored(StoredItem& item, GFile* file);
    virtual std::string print();
    virtual ObjectDisplable* clone();
    virtual EIdentified identifiedByPoint(const T2l::Canvas& canvas, const Point2F& pt);
protected:
//<DATA>
    Color  color_;
    double width_;
};

} //namespace T2l

Interaction

GObject enables easily define a custom object and how to display and refresh it. But this mechanism does not include user action itself. This is encapsulated in the class Cmd. Each Cmd class specialization solves partial task like is Line : GObject or Text : GObject creation, GObject movement, GObject deletion etc.

Active Cmd object handles actual user input. It is possible to create another Cmd object and switch the program functionality from one behavior to another. The object, where the active command is connected is CmdQueue. It has the only instance CmdQueue. Another command can be activated using the method CmdQueue::add(Cmd*, bool once).

In reality, is not a command kept directly in CmdQueue, but in object CmdStack. The last command in CmdStack is active. This enables you to start command and not to destroy the existing one. The first command can be completed, after the second is finalized.

The methods which the class Cmd reaches its functionality are:

  • enterPoint (Point2F&, Display&) - here you can enter the functionality, which will happen on click ( select object, enter point), implicitly implemented for the left mouse click, but you can enter xy x y on the command line as well or reimplement the invocation.
  • enterReset ( Display& ) - here you can implement functionality typical for escape or end. A typical sequence is then Point (Point ... Point Point Reset). No drag, no snaping no pirouettes. This is the approach known in the early days of drawing software and it is reinvented here.
  • enterMove ( Point2F&, Display& ) - there you can implement what is happening on a mouse moving.

Much better than one million of worlds is a simple example, we can draw the Line class from the QObject inheritance example:

class Cmd_draw_line : public Cmd {
public:
Cmd_draw_line(void) : Cmd("draw line"){}

virtual void enterPoint( const T2l::Point2F& pt, T2l::Display& ) {
   UpdateLock l;

   if (cmdpts_.count() == 0) {
      cmdpts_.add(Point2<double>(pt.x(), pt.y()));
   }
}

virtual void enterReset ( T2l::Display& view ) {
   new Line(cmdpts);
   cmdpts_.clean();

   pack->cleanDynamic();
}

virtual void enterMove(const T2l::Point2F& pt, T2l::Display& view) {
   if ( cmdpts_.count() == 0 ) return;

   T2l::EntityPack* pack = view.entityPack();
   pack->cleanDynamic();

   Line line(cmdpts_);
   line.appendPoint(pt);

   EntityList list;
   line->display(list, NULL);
   for ( long i = 0; i < list.count(); i++ ) {
      pack->addDynamic(list.get(i));
   }

   pack->dynamicRefresh();
}
 
virtual QString hint(void) const {
   if (cmdpts_.count() = 0) return "enter point";
   return "enter point or reset";
}
};

Some more explains to the code above: "draw line" is the name of a command. It can be used for displaying a button hint or for displaying active command. Virtual function hint() can be used for displaying actual hint. So there can be displayed for instance "draw line: enter point" as a hint what is the active command and what to do in the next step.

In this library, you can find some implementations of some commands. They are examples of what commands are:

  • Cmd_pan - shifts a display
  • Cmd_zoomBox - zooms display to given box
  • Cmd_void - this command does nothing. Good if there ought to be nothing doing command active.
  • Cmd_select - enables you to select an object

TentativeImplementation TODO

WidgetInteract, WidgetInteractCol::instance() TODO

Clone this wiki locally