#define XI_INTERNAL #include #include #include #include #include #include /////////////////////////////////////////////////////////// // TField_window /////////////////////////////////////////////////////////// #ifndef INCL_XI extern "C" { void xi_draw_3d_rect( WINDOW win, RCT* rctp, BOOLEAN well, int height, COLOR color_light, COLOR color_ctrl, COLOR color_dark ); } #endif void TField_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_FOCUS: if (ep->v.active) { WINDOW parent = xvt_vobj_get_parent(win); XI_OBJ* itf = xi_get_itf((XinWindow)parent); xi_set_focus(itf); } break; default: break; } TScroll_window::handler(win, ep); } bool TField_window::on_key(KEY k) { if (k == K_TAB || k == K_BTAB || k == K_F3 || k == K_F4) { const TMask& m = _owner->mask(); const short id = _owner->dlg(); const int start = m.id2pos(id); const int dir = (k == K_TAB || k == K_F3) ? +1 : -1; int pos = start; while (TRUE) { pos += dir; if (pos < 0) pos = m.fields()-1; if (pos >= m.fields()) pos = 0; if (pos == start) break; TMask_field& f = m.fld(pos); if (f.is_operable()) { f.set_focus(); return TRUE; } } } return TScroll_window::on_key(k); } void TField_window::update() { const WINDOW me = win(); if (CAMPI_SCAVATI) { const WINDOW pa = parent(); RCT rct; xvt_vobj_get_outer_rect(me, &rct); rct.left -= 2; rct.top -= 2; rct.right += 2; rct.bottom += 2; xi_draw_3d_rect((XinWindow)pa, (XinRect *) &rct, TRUE, 2, // qui MASK_LIGHT_COLOR, MASK_BACK_COLOR, MASK_DARK_COLOR); } xvt_dwin_clear(me, NORMAL_BACK_COLOR); set_font(); } TField_window::TField_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner) : _owner(owner) { if (owner != NULL) { create(x, y, dx, dy, "", WSF_HSCROLL | WSF_VSCROLL, W_PLAIN, parent); activate(owner->enabled()); if (owner->shown()) open(); } } /////////////////////////////////////////////////////////// // TWindowed field /////////////////////////////////////////////////////////// void TWindowed_field::enable(bool on) { TOperable_field::enable(on); if (_win) _win->activate(on); } void TWindowed_field::show(bool on) { TOperable_field::show(on); if (_win && _win->is_open() != on) { if (on) _win->open(); else _win->close(); } } void TWindowed_field::highlight() const { if (_win && active()) _win->set_focus(); } RCT& TWindowed_field::get_rect(RCT& r) const { if (_win) xvt_vobj_get_outer_rect(_win->win(), &r); else xvt_rect_set_empty(&r); return r; } void TWindowed_field::set_rect(const RCT& r) { if (_win) xvt_vobj_move(_win->win(), (RCT*)&r); } word TWindowed_field::class_id() const { return CLASS_WINDOWED_FIELD; } bool TWindowed_field::is_kind_of(word id) const { return id == CLASS_WINDOWED_FIELD || TOperable_field::is_kind_of(id); } const char* TWindowed_field::class_name() const { return "WINDOWED"; } short TWindowed_field::dlg() const { return _dlg ? _dlg : _ctl_data._dlg; } void TWindowed_field::parse_head(TScanner& scanner) { _ctl_data._width = scanner.integer(); _ctl_data._height = scanner.integer(); } TField_window* TWindowed_field::create_window(int x, int y, int dx, int dy, WINDOW parent) { // Must be always overridden and look like this return new TField_window(x, y, dx, dy, parent, this); } void TWindowed_field::create(short id, int x, int y, int dx, int dy, WINDOW parent) { if (parent == NULL_WIN) parent = mask().win(); _dlg = id; _win = create_window(x, y, dx, dy, parent); } void TWindowed_field::create(WINDOW parent) { create(_ctl_data._dlg, _ctl_data._x, _ctl_data._y, _ctl_data._width, _ctl_data._height, parent); } TWindowed_field::TWindowed_field(TMask* m) : TOperable_field(m), _dlg(0), _win(NULL) { } TWindowed_field::~TWindowed_field() { if (_win) delete _win; } #ifdef AGA_TREE /////////////////////////////////////////////////////////// // TNode_info /////////////////////////////////////////////////////////// class TNode_info : public TSortable { public: bool _valid : 1; bool _enabled : 1; bool _expandable : 1; bool _expanded : 1; TString _id; long _plusx; long _startx; long _endx; const TNode_info& operator =(const TNode_info& ni) { _valid = ni._valid; _enabled = ni._enabled; _expanded = ni._expanded; _expandable = ni._expandable; _id = ni._id; _plusx = ni._plusx; _startx = ni._startx; _endx = ni._endx; return ni; } virtual int compare(const TSortable& s) const { const TNode_info& ni = (const TNode_info&)s; return _id.compare(ni._id); } virtual bool ok() const { return _valid; } void reset() { _valid = false; } TNode_info() : _valid(false) { } virtual ~TNode_info() { } }; class TNode_info_array : public TObject { TArray _data; public: int last() const; int find(const TNode_info& ni) const; TNode_info& operator[](int index); const TNode_info& operator[](int index) const { return (const TNode_info&)_data[index]; } void reset(); }; TNode_info& TNode_info_array::operator[](int index) { CHECKD(index >= 0, "Bad index ", index); TNode_info* ni = (TNode_info*)_data.objptr(index); if (ni == NULL) { ni = new TNode_info; _data.add(ni, index); } return *ni; } void TNode_info_array::reset() { for (int i = _data.last(); i >= 0; i = _data.pred(i)) ((TNode_info*)_data.objptr(i))->reset(); } int TNode_info_array::last() const { int i; for (i = _data.last(); i >= 0; i = _data.pred(i)) if (_data[i].ok()) break; return i; } int TNode_info_array::find(const TNode_info& ni) const { int i; for (i = last(); i >= 0; i = _data.pred(i)) { if (((TNode_info*)_data.objptr(i))->compare(ni) == 0) break; } return i; } /////////////////////////////////////////////////////////// // TTree_window /////////////////////////////////////////////////////////// class TTree_window : public TField_window { TTree* _tree; bool _hide_leaves; long _first_line; // Prima riga disegnata TNode_info_array _node_info; TNode_info _curr_info; // Nodo attualmente selezionato TAuto_token_string _header; int _headlines; /*static*/ int _row_height; static bool _tree_locked; protected: // TWindow virtual void update(); virtual bool on_key(KEY key); virtual void handler(WINDOW win, EVENT* ep); int row_height() const { return _row_height; } PNT log2dev(long x, long y) const; TPoint dev2log(const PNT& p) const; protected: // Internal use static bool callback_draw_node(TTree& node, void* jolly, word); void update_header(); void draw_plus_minus(); void draw_text(int x, int y, const TString& str); int info2index(const TNode_info& ni) const; bool index2info(long index, TNode_info& ni); public: TTree* tree() const { return _tree; } void set_tree(TTree* tree) { _tree = tree; _first_line = -1; } void hide_leaves(bool yes) { _hide_leaves = yes; } bool select_current(); bool goto_selected(); void set_header(const char* head); void set_row_height(int rh); TTree_window(int x, int y, int dx, int dy, WINDOW parent, TTree_field* owner); virtual ~TTree_window() { } }; bool TTree_window::_tree_locked = false; const int TABX = 3; struct TUpdate_info { TTree_window* _win; TToken_string _str; long _x, _y; long _firsty, _lasty; long _jolly; int _headlines; TNode_info_array* _node_info; TNode_info* _curr_info; }; PNT TTree_window::log2dev(long x, long y) const { if (_headlines > 0) y += _headlines; if (autoscrolling()) { if (_pixmap) { x -= origin().x * CHARX; y -= origin().y * _row_height; } else { x -= origin().x; y -= origin().y; } } PNT pnt; pnt.h = (int)x; pnt.v = (int)y; if (!_pixmap) { pnt.h *= CHARX; pnt.v *= _row_height; } return pnt; } TPoint TTree_window::dev2log(const PNT& dp) const { PNT p = dp; if (_headlines > 0) p.v -= _headlines * _row_height; TPoint pnt(_pixmap ? p.h : p.h/CHARX, _pixmap ? p.v : p.v/_row_height); return pnt; } void TTree_window::draw_text(int x, int y, const TString& str) { int start = 0, pos = 0; while (pos >= 0) { pos = str.find(" ", start); const TString& mid = str.sub(start, pos); if (!mid.blank()) stringat(x + start, y, mid); start = pos+2; } } bool TTree_window::callback_draw_node(TTree& node, void* jolly, word when) { TUpdate_info* ui = (TUpdate_info*)jolly; if (when == SCAN_PRE_ORDER) { if (ui->_y >= ui->_firsty && ui->_y <= ui->_lasty) { node.curr_id(ui->_str); const bool is_selected = ui->_str == ui->_curr_info->_id; const bool is_enabled = node.enabled(); const bool is_marked = node.marked(); int text_len = 0; if (node.get_description(ui->_str)) { text_len = ui->_str.len(); if (is_selected) ui->_win->set_color(FOCUS_COLOR, FOCUS_BACK_COLOR); else ui->_win->set_color(is_enabled ? NORMAL_COLOR : DISABLED_COLOR, is_marked ? REQUIRED_BACK_COLOR : NORMAL_BACK_COLOR); ui->_win->draw_text(int(ui->_x+2), int(ui->_y), ui->_str); } const int ry = int(ui->_y - ui->_firsty); int by; for (by = ry-1; by >= 0; by--) { long rx = (*ui->_node_info)[by]._startx; if (rx < ui->_x) break; } const PNT p = ui->_win->log2dev(ui->_x, ui->_y); const WINDOW win = ui->_win->win(); ui->_win->set_pen(DISABLED_BACK_COLOR); const int rh = ui->_win->row_height(); PNT q; q.h = p.h; q.v = p.v + rh/2; xvt_dwin_draw_set_pos(win, q); q.h -= TABX*CHARX - 3*CHARX/2; xvt_dwin_draw_line(win, q); q.v = (by+1+ui->_headlines)*rh; xvt_dwin_draw_line(win, q); TImage* bmp = node.image(is_selected); if (bmp) { const int x = p.h; const int y = p.v + (rh - bmp->height()) / 2; if (is_enabled) bmp->draw(win, x, y); else { TImage dis(*bmp); for (int j = dis.height()-1; j >= 0; j--) for (int i = dis.width() - (j&1 ? 2 : 1); i >= 0; i-=2) dis.set_pixel(i, j, NORMAL_BACK_COLOR); dis.draw(win, x, y); } } TNode_info& ni = (*ui->_node_info)[ry]; node.curr_id(ni._id); ni._valid = true; ni._startx = ui->_x; ni._endx = ui->_x + text_len + 2; ni._enabled = is_enabled; ni._expandable = is_enabled && node.has_son(); if (ni._expandable) { ni._plusx = ui->_x - TABX + 1; ni._expanded = node.expanded(); } else { ni._plusx = 0; ni._expanded = false; } } ui->_y++; ui->_x += TABX; if (ui->_x > ui->_jolly) ui->_jolly = ui->_x; } else if (when == SCAN_IN_ORDER) { ui->_x -= TABX; if (ui->_y > ui->_lasty) return true; } return false; } void TTree_window::draw_plus_minus() { const long firsty = origin().y; const int last_drawn = _node_info.last(); for (int i = last_drawn; i >= 0; i--) { TNode_info& ni = _node_info[i]; if (ni._plusx > 0) { if (ni._expanded) { bool spudorato = i == last_drawn; // Falso espandibile if (!spudorato) { const TNode_info& nni = _node_info[i+1]; spudorato = nni._startx <= ni._startx; } if (spudorato) { ni._expandable = false; ni._expanded = false; ni._plusx = 0; continue; } } WINDOW w = win(); PNT r = log2dev(ni._plusx, firsty + i); r.v += _row_height/2; r.h += CHARX/2; RCT rct; rct.left = r.h - 4; rct.top = r.v - 4; rct.right = r.h + 5; rct.bottom = r.v + 5; set_pen(NORMAL_COLOR); set_brush(NORMAL_BACK_COLOR); xvt_dwin_draw_rect(w, &rct); PNT f, t; f.h = rct.left+2; f.v = r.v; t.h = rct.right+-2; t.v = r.v; xvt_dwin_draw_set_pos(w, f); xvt_dwin_draw_line(w, t); if (!ni._expanded) { f.h = r.h; f.v = rct.top+2; t.h = r.h; t.v = rct.bottom-2; xvt_dwin_draw_set_pos(w, f); xvt_dwin_draw_line(w, t); } } } } void TTree_window::set_header(const char* head) { _header = head; _headlines = _header.items(); } void TTree_window::update_header() { if (_headlines > 0) { autoscroll(false); set_brush(MASK_BACK_COLOR); bar(0,-_headlines,columns(),0); autoscroll(true); set_opaque_text(false); for (int i = 0; i < _headlines; i++) { const TFixed_string str(_header.get(i)); draw_text(2, int(origin().y+i-_headlines), str); } } } void TTree_window::update() { TField_window::update(); if (_tree == NULL) return; update_header(); TUpdate_info ui; ui._win = this; ui._x = 0; ui._y = 0; ui._firsty = origin().y; ui._lasty = ui._firsty + rows(); ui._jolly = 0; ui._headlines = _headlines; ui._node_info = &_node_info; ui._curr_info = &_curr_info; bool ok = false; if (_first_line > 0) { const long index = origin().y - _first_line; TNode_info ni; if (index2info(index, ni)) { ok = _tree->goto_node(ni._id); ui._x = ni._startx; ui._y = ui._firsty; } } if (!ok) { ok = _tree->goto_root(); if (!ok) return; } _node_info.reset(); set_opaque_text(true); word flags = SCAN_PRE_ORDER | SCAN_IN_ORDER | SCAN_IGNORING_UNEXPANDED; if (_hide_leaves) flags |= SCAN_IGNORING_LEAVES; _tree->scan_depth_first(callback_draw_node, &ui, flags); while (ui._y < ui._lasty) { if (_tree->goto_father()) { ui._x -= TABX; if (_tree->goto_rbrother()) _tree->scan_depth_first(callback_draw_node, &ui, flags); } else break; } draw_plus_minus(); set_scroll_max(ui._jolly+columns(), ui._y); _first_line = ui._firsty; } // Fa diventare il nodo corrente selezionato bool TTree_window::select_current() { if (_tree) _tree->curr_id(_curr_info._id); return _tree != NULL; } // Salta al nodo correntemente selezionato bool TTree_window::goto_selected() { bool ok = false; if (_tree) ok = _tree->goto_node(_curr_info._id); return ok; } void TTree_window::set_row_height(int rh) { if (rh <= 0) rh = CHARY+2; _row_height = rh; } int TTree_window::info2index(const TNode_info& info) const { return _node_info.find(info); } bool TTree_window::index2info(long index, TNode_info& ni) { bool ok = false; const int last = _node_info.last(); if (index == -1) { if (index2info(0, ni) && _tree->goto_node(ni._id)) { ok = _tree->goto_lbrother(); if (!ok) { ok = _tree->goto_father(); ni._startx -= TABX; } if (ok) _tree->curr_id(ni._id); } } else if (index == last+1 && last >= 0) { if (index2info(last, ni) && _tree->goto_node(ni._id)) { ok = _tree->expanded() && _tree->goto_firstson(); if (ok && _hide_leaves && !_tree->has_son()) { _tree->goto_node(ni._id); // Ritorno al padre perche' ignoro le foglie ok = false; } if (!ok) { ok = _tree->goto_rbrother(); ni._startx += TABX; } if (ok) { _tree->curr_id(ni._id); } } } else if (index >= 0 && index <= last) { TNode_info& info = _node_info[int(index)]; ok = info.ok(); if (ok) ni = info; } return ok; } bool TTree_window::on_key(KEY key) { if (_tree == NULL || _tree_locked) return false; if (key == K_RIGHT) { if (_tree->goto_node(_curr_info._id) && !_tree->expanded() && _tree->has_son()) key = K_ENTER; else key = K_DOWN; } if (key == K_LEFT) { if (_tree->goto_node(_curr_info._id) && _tree->expanded()) key = K_ENTER; else key = K_UP; } if (key == K_UP || key == K_DOWN) { _tree_locked = true; int index = info2index(_curr_info); if (key == K_UP) index--; else index++; bool ok = false; bool scroll = false; TNode_info ni; if (index2info(index, ni)) { ok = _tree->goto_node(ni._id); scroll = ok && (index < 0 || index > _node_info.last()); } else { const int index = key == K_UP ? 0 : _node_info.last(); ok = index2info(index, ni) && _tree->goto_node(ni._id); } if (ok && _curr_info != ni) { _tree->curr_id(_curr_info._id); owner().on_key(K_SPACE); if (!scroll) { force_update(); do_events(); } } _tree_locked = false; if (!scroll) return true; } if (key == K_ENTER) { _tree_locked = true; if (_tree->goto_node(_curr_info._id)) { if (_tree->has_son()) { bool ok; if (_tree->expanded()) ok = _tree->shrink(); else ok = _tree->expand(); if (ok) { force_update(); do_events(); // Make sure of being well positioned after the redraw!!! _tree->goto_node(_curr_info._id); } } owner().on_key(K_CTRL + K_SPACE); } _tree_locked = false; } return TField_window::on_key(key); } void TTree_window::handler(WINDOW win, EVENT* ep) { switch(ep->type) { case E_MOUSE_DBL: case E_MOUSE_DOWN: if (_tree && !_tree_locked) { _tree_locked = true; const TPoint lp = dev2log(ep->v.mouse.where); const int c = (int)lp.x; const int r = (int)lp.y; TNode_info ni; bool ok = index2info(r, ni); if (ok && (c == ni._plusx || (c >= ni._startx && c < ni._endx)) && _tree->goto_node(ni._id)) { if (c == ni._plusx || (ni._expandable && ep->type == E_MOUSE_DBL && c <= ni._plusx+3)) { if (_tree->expanded()) ok = _tree->shrink(); else ok = _tree->expand(); if (ok) { owner().on_key(K_SHIFT + K_SPACE); // Expansion owner().on_key(K_SPACE); // Selection } } else { KEY key = K_SPACE; if (ep->type == E_MOUSE_DBL) key += K_CTRL; // Double click selection owner().on_key(key); } if (ok) { _curr_info = ni; force_update(); } } _tree_locked = false; } break; default: TField_window::handler(win, ep); break; } } TTree_window::TTree_window(int x, int y, int dx, int dy, WINDOW parent, TTree_field* owner) : TField_window(x, y, dx, dy, parent, owner), _tree(NULL), _hide_leaves(false), _headlines(0) { set_row_height(-1); // Compute default row height } #else /////////////////////////////////////////////////////////// // TControl_host_window /////////////////////////////////////////////////////////// class TControl_host_window : public TField_window { protected: WINDOW _ctrl; protected: void handler(WINDOW win, EVENT* ep); TControl_host_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner); }; void TControl_host_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_SIZE: if (_ctrl != NULL_WIN) { RCT rct; xvt_rect_set(&rct, 0, 0, ep->v.size.width, ep->v.size.height); xvt_vobj_move(_ctrl, &rct); } break; default: break; } TField_window::handler(win, ep); } TControl_host_window::TControl_host_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner) : TField_window(x, y, dx, dy, parent, owner), _ctrl(NULL_WIN) { set_scroll_max(0, 0); // Get rid of that useless scrollbars } /////////////////////////////////////////////////////////// // TTree_window /////////////////////////////////////////////////////////// class TTree_window : public TControl_host_window { TTree* _tree; bool _hide_leaves; TAuto_token_string _header; private: void create_children(XVT_TREEVIEW_NODE node); void handle_tree_event(EVENT* ep); bool add_child(XVT_TREEVIEW_NODE parent); protected: // TWindow virtual void update(); virtual void handler(WINDOW win, EVENT* ep); virtual void force_update(); public: TTree* tree() const { return _tree; } void set_tree(TTree* tree); void hide_leaves(bool yes) { _hide_leaves = yes; } bool select_current(); bool goto_selected(); void set_header(const char* head); void set_row_height(int rh); TTree_window(int x, int y, int dx, int dy, WINDOW parent, TTree_field* owner); virtual ~TTree_window() { } }; bool TTree_window::add_child(XVT_TREEVIEW_NODE parent) { XVT_TREEVIEW_NODE_TYPE type = _tree->has_son() ? XVT_TREEVIEW_NODE_NONTERMINAL : XVT_TREEVIEW_NODE_TERMINAL; if (_hide_leaves && type == XVT_TREEVIEW_NODE_TERMINAL) return false; TString id; _tree->curr_id(id); TString desc; _tree->get_description(desc); XVT_IMAGE ii = NULL, ic = NULL, ie = NULL; TImage* im_nor = _tree->image(false); if (type == XVT_TREEVIEW_NODE_NONTERMINAL) { TImage* im_sel = _tree->image(true); ic = im_nor->xvt_image(); ie = im_sel->xvt_image(); } else ii = im_nor->xvt_image(); XVT_TREEVIEW_NODE child = xvt_treeview_add_child_node(_ctrl, parent, type, ii, ic, ie, desc, NULL, id); if (type == XVT_TREEVIEW_NODE_NONTERMINAL && _tree->expanded()) xvt_treeview_expand_node(_ctrl, child, FALSE); return true; } void TTree_window::create_children(XVT_TREEVIEW_NODE node) { bool ok = false; TString id; if (_tree != NULL) { if (node != NULL) id = xvt_treeview_get_node_data(_ctrl, node); if (id.empty()) // Sono sulla radice { node = xvt_treeview_get_root_node(_ctrl); ok = _tree->goto_root(); } else { _tree->goto_node(id); ok = _tree->goto_firstson(); } } xvt_treeview_remove_node_children(_ctrl, node); for (; ok; ok = _tree->goto_rbrother()) add_child(node); // Riposiziona per benino l'alberello if (id.empty()) _tree->goto_root(); else _tree->goto_node(id); } void TTree_window::set_tree(TTree* tree) { _tree = tree; if (_tree != NULL) { // Memorizza la posizione dell'albero per dopo ... TString curr; tree->curr_id(curr); create_children(NULL); // Rigenera i figli della radice tree->goto_node(curr); // Riporta la selezione sul nodo memorizzato } } void TTree_window::handle_tree_event(EVENT* ep) { XVT_TREEVIEW_NODE node = ep->v.ctl.ci.v.treeview.node; const TString id = (const char*)xvt_treeview_get_node_data(_ctrl, node); if (_tree->goto_node(id)) { if (ep->v.ctl.ci.v.treeview.sgl_click || ep->v.ctl.ci.v.treeview.dbl_click) { KEY key = K_SPACE; // Single click selection if (ep->v.ctl.ci.v.treeview.dbl_click) key += K_CTRL; // Double click selection if (owner().on_key(key) && _tree->goto_node(id)) { // Aggiorna testo ed immagini che possono essere cambiate XVT_IMAGE ii = NULL, ic = NULL, ie = NULL; TImage* im_nor = _tree->image(false); if (_tree->has_son()) { TImage* im_sel = _tree->image(true); ic = im_nor->xvt_image(); ie = im_sel->xvt_image(); } else ii = im_nor->xvt_image(); xvt_treeview_set_node_images(_ctrl, node, ii, ic, ie); TString desc; _tree->get_description(desc); xvt_treeview_set_node_string(_ctrl, node, desc); } } else { int nWhat = 0; if (ep->v.ctl.ci.v.treeview.expanded) nWhat |= 0x1; if (ep->v.ctl.ci.v.treeview.collapsed) nWhat |= 0x2; switch (nWhat) { case 0x1: // Expanded _tree->expand(); owner().on_key(K_SHIFT + K_SPACE); break; case 0x2: // Collapsed _tree->shrink(); break; case 0x3: // Expanding _tree->expand(); create_children(node); owner().on_key(K_SHIFT + K_SPACE); owner().on_key(K_SPACE); break; default : break; } } } } void TTree_window::update() { if (_header.full()) { set_brush(MASK_BACK_COLOR); bar(0, 0, columns(), _header.items()); short x = 3, y = 0; FOR_EACH_TOKEN(_header, row) stringat(x, y++, row); } } void TTree_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_CONTROL: if (ep->v.ctl.ci.type == WC_TREE && _tree != NULL) handle_tree_event(ep); break; default: break; } TControl_host_window::handler(win, ep); } bool TTree_window::select_current() { XVT_TREEVIEW_NODE selected = NULL; // Nodo da selezionare (se mai lo trovero') if (_tree != NULL) { xvt_treeview_suspend(_ctrl); // Sospendo le notifiche degli eventi TString id; _tree->curr_id(id); // id del nodo corrente dell'albero // Controllo se il tree control e' gia' posizionato bene XVT_TREEVIEW_NODE cursel = xvt_treeview_get_selected_node(_ctrl); if (cursel != NULL) { const char* curdata = xvt_treeview_get_node_data(_ctrl, cursel); if (id == curdata) { xvt_treeview_resume(_ctrl); return true; } } TString_array a; a.add(id); // Creo la lista dei progenitori while (_tree->goto_father()) { const int i = a.add(EMPTY_STRING); _tree->curr_id(a.row(i)); _tree->expand(); // Nel caso non fosse gia' espanso } // Scandisco i progenitori partendo dalla radice XVT_TREEVIEW_NODE parent = NULL; // was xvt_treeview_get_root_node(_ctrl); bool killed = false; // Ho interrotto "bruscamente" la ricerca? FOR_EACH_ARRAY_ROW_BACK(a, r, row) { if (killed) break; for (int i = 0; ; i++) { XVT_TREEVIEW_NODE child = xvt_treeview_get_child_node(_ctrl, parent, i); if (child == NULL && i == 0) // Forse non c'e' nessun figlio ... { create_children(parent); // ... sara' vero? child = xvt_treeview_get_child_node(_ctrl, parent, i); } if (child == NULL) // Certamente non ci sono piu' figli { //killed = true; // Non ho trovato quello che cercavo: esco subito break; } const char* data = xvt_treeview_get_node_data(_ctrl, child); if (*row == data) { selected = child; if (*row == id) // Ho finito killed = true; else { parent = child; xvt_treeview_expand_node(_ctrl, child, FALSE); } break; } } } if (selected != NULL) xvt_treeview_select_node(_ctrl, selected, TRUE); xvt_treeview_resume(_ctrl); // Riattivo le notifiche degli eventi _tree->goto_node(id); if (selected != NULL && _tree->expanded()) xvt_treeview_expand_node(_ctrl, selected, FALSE); } return selected != NULL; } bool TTree_window::goto_selected() { bool ok = false; XVT_TREEVIEW_NODE child = xvt_treeview_get_selected_node(_ctrl); if (child != NULL) { const char* data = (const char*)xvt_treeview_get_node_data(_ctrl, child); ok = _tree->goto_node(data); } return ok; } void TTree_window::set_header(const char* head) { if (_header != head) { const int old_headlines = _header.items(); _header = head; const int new_headlines = _header.items(); if (new_headlines != old_headlines) { RCT rctree; xvt_vobj_get_client_rect(win(), &rctree); rctree.top += new_headlines * CHARY; xvt_vobj_move(_ctrl, &rctree); } force_update(); } } void TTree_window::set_row_height(int rh) { } TTree_window::TTree_window(int x, int y, int dx, int dy, WINDOW parent, TTree_field* owner) : TControl_host_window(x, y, dx, dy, parent, owner), _tree(NULL), _hide_leaves(false) { RCT rct; xvt_vobj_get_client_rect(win(), &rct); _ctrl = xvt_treeview_create(win(), &rct, "", 0, (long)this, owner->dlg(), NULL, NULL, NULL, 0, CHARY+2); } #endif /////////////////////////////////////////////////////////// // TTree_field /////////////////////////////////////////////////////////// word TTree_field::class_id() const { return CLASS_TREE_FIELD; } bool TTree_field::is_kind_of(word cid) const { return cid == CLASS_TREE_FIELD || TWindowed_field::is_kind_of(cid); } #define tree_win() ((TTree_window&)win()) TTree* TTree_field::tree() const { return tree_win().tree(); } void TTree_field::set_tree(TTree* tree) { TTree_window& tv = tree_win(); tv.set_tree(tree); tv.select_current(); } void TTree_window::force_update() { set_tree(tree()); } void TTree_field::hide_leaves(bool yes) { tree_win().hide_leaves(yes); } bool TTree_field::select_current() { return tree_win().select_current(); } bool TTree_field::goto_selected() { return tree_win().goto_selected(); } void TTree_field::set_header(const char* head) { tree_win().set_header(head); } void TTree_field::set_row_height(int rh) { tree_win().set_row_height(rh); } TField_window* TTree_field::create_window(int x, int y, int dx, int dy, WINDOW parent) { return new TTree_window(x, y, dx, dy, parent, this); } /////////////////////////////////////////////////////////// // TOutlook_field /////////////////////////////////////////////////////////// class TOutlook_window : public TControl_host_window { public: virtual void handler(WINDOW win, EVENT* ep); public: int add_item(short icon, const char* text, int flags); bool select(int item, bool on); int selected() const; TOutlook_window(int x, int y, int dx, int dy, WINDOW parent, TOutlook_field* owner); }; void TOutlook_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_CONTROL: if (ep->v.ctl.ci.type == WC_OUTLOOKBAR) { owner().on_key(K_SPACE); return; } break; default: break; } TControl_host_window::handler(win, ep); } int TOutlook_window::add_item(short icon, const char* text, int flags) { return xvt_list_add_item(_ctrl, icon, text, flags); } bool TOutlook_window::select(int item, bool on) { return xvt_list_set_sel(_ctrl, item, on) != FALSE; } int TOutlook_window::selected() const { return xvt_list_get_sel_index(_ctrl); } TOutlook_window::TOutlook_window(int x, int y, int dx, int dy, WINDOW parent, TOutlook_field* owner) : TControl_host_window(x, y, dx, dy, parent, owner) { WIN_DEF wd; memset(&wd, 0, sizeof(wd)); wd.wtype = WC_OUTLOOKBAR; wd.v.ctl.ctrl_id = owner->dlg(); wd.rct = resize_rect(x, y, dx, dy, wd.wtype, parent); _ctrl = xvt_ctl_create_def(&wd, win(), 0); } word TOutlook_field::class_id() const { return CLASS_OUTLOOK_FIELD; } bool TOutlook_field::is_kind_of(word cid) const { return cid == CLASS_OUTLOOK_FIELD || TWindowed_field::is_kind_of(cid); } TField_window* TOutlook_field::create_window(int x, int y, int dx, int dy, WINDOW parent) { return new TOutlook_window(x, y, dx, dy, parent, this); } void TOutlook_field::create(short dlg, int x, int y, int dx, int dy, WINDOW parent) { construct(dlg, "", x, y, dy, parent, "", dx); } int TOutlook_field::add_item(short icon, const char* text, int flags) { TOutlook_window& ow = (TOutlook_window&)win(); return ow.add_item(icon, text, flags); } void TOutlook_field::set_window_data(const char* data) { TOutlook_window& ow = (TOutlook_window&)win(); const int sel = atoi(data); _str.cut(0) << sel; ow.select(sel, true); } const TString& TOutlook_field::get_window_data() { TOutlook_window& ow = (TOutlook_window&)win(); _str.cut(0) << ow.selected(); return _str; } void TOutlook_field::set(const char* data) { set_window_data(data); set_dirty(); } const TString& TOutlook_field::get() const { return _str; } bool TOutlook_field::on_key(KEY key) { if (key == K_SPACE) { get_window_data(); set_dirty(); on_hit(); return true; } return TWindowed_field::on_key(key); }