#include <ubit/ubit.hpp>
#include <ubit/ext/utree.hpp>


class BNode;

class Builder : public UBox {

  class Controls {
  public:
    UButton new_btn, open_btn, save_btn, sketch_btn, quit_btn;
    UButton unlink_btn, undel_btn, del_btn;
    UButton rebuild_btn, code_btn, prop_btn, connex_btn;
    
    UMenubar menubar;
    UBar toolbar;
    
    Controls(Builder*);
  } controls;
  
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  
  class Infos {
  public:
    UBox panel;
    
    Infos(Builder*);
  } infos;
  
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  class Status {
  public:
    UBox panel;
    
    Status(Builder*);
  } status;
  
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  
  class BBoard {
public:
    UScrollpane spane;
    UBox canvas;

    BBoard(Builder*);
  } bboard;
  
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  class Classes {
  public:
    UBox panel;
    
    Classes(Builder*);
  } classes;

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  
public:
  Builder();

  void initTree();

  BNode* getCurrentNode() const;

  void addToNode(BNode* parent, BNode* child);
  void addToCurrentNode(BNode* child);

  void removeNode(BNode*);
  void removeCurrentNode();

  uptr<class UTreebox> tree;
  uptr<UDialog> preview;
};

/* ==================================================== [Elc:03] ======= */
/* ==================================================== ======== ======= */

struct BNode : public UNode {
public:
  BNode(class UTreebox& tree, const UArgs& title,
        class ClassDef* def, UBrick* obj);
  ~BNode();
  
  class ClassDef* getDef() const {return def;}
  UBrick* getObj() const {return obj;}
  void setObj(UBrick*);
  
private:
  uptr<UBrick> obj;
  class ClassDef* def;
};

/* ==================================================== [Elc:03] ======= */
/* ==================================================== ======== ======= */

struct ClassDef : public UItem {
  UStr name;
  int no;
  
  ClassDef(const char* _name) : name(_name), no(1) {}
  virtual void createNode(Builder*) = 0;
};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

struct BrickClassDef : public ClassDef {
  UBrick& (*obj_constr)();
  
  BrickClassDef(Builder*, const char* name,
                UBrick& (*obj_constr)());
  
  virtual void createNode(Builder*);
};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

struct GroupClassDef : public ClassDef {
  UGroup& (*obj_constr)(const UArgs&);
  bool add_name;
  
  GroupClassDef(Builder*, const char* name,
                UGroup& (*obj_constr)(const UArgs&),
           bool add_name = false);
  
  virtual void createNode(Builder*);
};

/* ==================================================== [Elc:03] ======= */
/* ==================================================== ======== ======= */

