#define XI_INTERNAL #include #include #include #include #include #include #include #include // DI "Prompt|field" static TString_array _items; /////////////////////////////////////////////////////////// // TField_window /////////////////////////////////////////////////////////// long 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; case E_MOUSE_DOWN: if (ep->v.mouse.button == 1 && _owner != NULL) { _owner->on_key(K_F11); return 0L; } break; default: break; } return 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); xvt_rect_inflate(&rct, 2, 2); xi_draw_3d_rect((XinWindow)pa, (XinRect*)&rct, TRUE, 2, MASK_LIGHT_COLOR, MASK_BACK_COLOR, MASK_DARK_COLOR); } xvt_dwin_clear(me, NORMAL_BACK_COLOR); set_font(); } // Serve quando si chiama il costruttore senza owner void TField_window::set_owner(TWindowed_field* o) { _owner = o; } TField_window::TField_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner) : _owner(owner) { if (owner != NULL) { CHECK(parent, "Null control parent"); 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_null(&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; } /////////////////////////////////////////////////////////// // TControl_host_window /////////////////////////////////////////////////////////// long TControl_host_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_FOCUS: if (ep->v.active) { if (_ctrl != NULL_WIN && _ctrl != win) xvt_scr_set_focus_vobj(_ctrl); owner().mask().notify_focus_field(owner().dlg()); return 0L; } break; 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; case E_UPDATE: if (_ctrl != NULL_WIN) return 0L; // Inutile disegnare: _ctrl occupa tutta la client area break; default: break; } return TField_window::handler(win, ep); } void TControl_host_window::set_focus() { if (_ctrl != NULL_WIN) xvt_scr_set_focus_vobj(_ctrl); } 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) { if (win() != 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; protected: TAuto_token_string _header; private: virtual void create_children(XVT_TREEVIEW_NODE node); virtual void handle_tree_event(EVENT* ep); virtual bool add_child(XVT_TREEVIEW_NODE parent); protected: // TWindow virtual void update(); virtual long handler(WINDOW win, EVENT* ep); virtual void force_update(); public: virtual TTree* tree() const { return _tree; } virtual void set_tree(TTree* tree); virtual void hide_leaves(bool yes) { _hide_leaves = yes; } virtual bool select_current(); virtual bool goto_selected(); virtual void set_header(const char* head); virtual 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->could_have_son() ? XVT_TREEVIEW_NODE_NONTERMINAL : XVT_TREEVIEW_NODE_TERMINAL; if (_hide_leaves && type == XVT_TREEVIEW_NODE_TERMINAL) return false; XVT_IMAGE ii = NULL, ic = NULL, ie = NULL; TImage* im_nor = _tree->image(false); if (im_nor != NULL) { 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(); } TString256 desc; _tree->get_description(desc); TString256 id; _tree->curr_id(id); XVT_TREEVIEW_NODE child = xvt_treeview_add_child_node(_ctrl, parent, type, ii, ic, ie, desc, NULL, id); if (child != NULL) { if (!_tree->enabled()) xvt_treeview_enable_node(_ctrl, child, FALSE); if (_tree->marked()) xvt_treeview_set_node_bold(_ctrl, child, TRUE); if (type == XVT_TREEVIEW_NODE_NONTERMINAL && _tree->expanded()) { for (bool ok = _tree->goto_firstson(); ok; ok = _tree->goto_rbrother()) add_child(child); xvt_treeview_expand_node(_ctrl, child, FALSE); } } _tree->goto_node(id); 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 if (tree->goto_node(curr)) // Riporta la selezione sul nodo memorizzato select_current(); } } void TTree_window::handle_tree_event(EVENT* ep) { XVT_TREEVIEW_NODE node = ep->v.ctl.ci.v.treeview.node; if (node == NULL) // Click fuori da tutto { if (ep->v.ctl.ci.v.treeview.dbl_click) owner().on_key(K_F11); else if (ep->v.ctl.ci.v.treeview.sgl_click) owner().on_key(K_F8); return; } 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()) { clear(MASK_BACK_COLOR); set_color(PROMPT_COLOR, MASK_BACK_COLOR); short x = 3, y = 0; FOR_EACH_TOKEN(_header, row) stringat(x, y++, row); } } long 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); return 0L; } break; case E_UPDATE: update(); // TControl_host_window non lo fa return 0L; default: break; } return TControl_host_window::handler(win, ep); } bool TTree_window::select_current() { XVT_TREEVIEW_NODE nextsel = NULL; // Nodo da selezionare (se mai lo trovero') if (_tree != NULL) { 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); nextsel = xvt_treeview_find_node_string(_ctrl, id); if (nextsel != NULL && cursel == nextsel) return true; if (nextsel == NULL) { xvt_treeview_suspend(_ctrl); // Sospendo le notifiche degli eventi 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) { nextsel = child; if (*row == id) // Ho finito killed = true; else { parent = child; xvt_treeview_expand_node(_ctrl, child, FALSE); } break; } } } xvt_treeview_resume(_ctrl); // Riattivo le notifiche degli eventi _tree->goto_node(id); // Riposiziono l'albero } if (nextsel != NULL) { xvt_treeview_select_node(_ctrl, nextsel, TRUE); if (_tree->expanded()) xvt_treeview_expand_node(_ctrl, nextsel, FALSE); } } return nextsel != 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) { // TBI } 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) { if (owner != NULL && owner->class_id() == CLASS_TREE_FIELD) { 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); XVT_COLOR_COMPONENT xcc[8]; memset(xcc, 0, sizeof(xcc)); xcc[0].type = XVT_COLOR_BACKGROUND; xcc[0].color = NORMAL_BACK_COLOR; xcc[1].type = XVT_COLOR_FOREGROUND; xcc[1].color = NORMAL_COLOR; xcc[2].type = XVT_COLOR_HIGHLIGHT; xcc[2].color = FOCUS_BACK_COLOR; xcc[3].type = XVT_COLOR_SELECT; xcc[3].color = FOCUS_COLOR; xcc[4].type = XVT_COLOR_BLEND; xcc[4].color = MASK_BACK_COLOR; xcc[5].type = XVT_COLOR_TROUGH; xcc[5].color = DISABLED_COLOR; xvt_ctl_set_colors(_ctrl, xcc, XVT_COLOR_ACTION_SET); } } /////////////////////////////////////////////////////////// // 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); } void TTree_field::force_update() { set_tree(tree()); } 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 long 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; int items() const; void clear(); TOutlook_window(int x, int y, int dx, int dy, WINDOW parent, TOutlook_field* owner); }; long 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 0L; } break; default: break; } return 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); } int TOutlook_window::items() const { return xvt_list_count(_ctrl); } void TOutlook_window::clear() { xvt_list_clear(_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) { XVT_COLOR_COMPONENT xcc[4]; memset(xcc, 0, sizeof(xcc)); xcc[0].type = XVT_COLOR_BACKGROUND; xcc[0].color = MASK_BACK_COLOR; xcc[1].type = XVT_COLOR_FOREGROUND; xcc[1].color = PROMPT_COLOR; xcc[2].type = XVT_COLOR_HIGHLIGHT; xcc[2].color = MASK_LIGHT_COLOR; WIN_DEF wd[2]; memset(&wd, 0, sizeof(wd)); wd->wtype = WC_OUTLOOKBAR; wd->v.ctl.ctrl_id = owner->dlg(); wd->v.ctl.font_id = xvtil_default_font(true); // Fat font wd->rct = resize_rect(x, y, dx, dy, wd->wtype, parent); wd->ctlcolors = xcc; _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); } void TOutlook_field::clear() { TOutlook_window& ow = (TOutlook_window&)win(); ow.clear(); } int TOutlook_field::items() const { TOutlook_window& ow = (TOutlook_window&)win(); return ow.items(); } 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); } /////////////////////////////////////////////////////////// // TSlider_window /////////////////////////////////////////////////////////// class TSlider_window : public TField_window { public: void set(int pos); int get() const; void set_range(int mi, int ma); TSlider_window(int x, int y, int dx, int dy, WINDOW parent, TSlider_field* owner); }; void TSlider_window::set_range(int mi, int ma) { if (mi != 0) { ma -= mi; mi = 0; } if (ma < mi) ma = 100; xvt_sbar_set_range(win(), HVSLIDER, mi, ma); } void TSlider_window::set(int pos) { xvt_sbar_set_pos(win(), HVSLIDER, pos); } int TSlider_window::get() const { return xvt_sbar_get_pos(win(), HVSLIDER); } TSlider_window::TSlider_window(int x, int y, int dx, int dy, WINDOW parent, TSlider_field* owner) : TField_window(0, 0, 0, 0, NULL, NULL) { XVT_COLOR_COMPONENT xcc[2]; memset(xcc, 0, sizeof(xcc)); xcc[0].type = XVT_COLOR_BLEND; xcc[0].color = MASK_BACK_COLOR; set_owner(owner); WIN_DEF wd; memset(&wd, 0, sizeof(wd)); wd.rct = resize_rect(x, y, dx, dy, wd.wtype, parent); wd.wtype = (wd.rct.right-wd.rct.left) > (wd.rct.bottom-wd.rct.top) ? WC_HSLIDER : WC_VSLIDER; wd.ctlcolors = xcc; wd.v.ctl.ctrl_id = owner->dlg(); real mi, ma; owner->range(mi, ma); const long limit = ma.integer() - mi.integer(); set_win(xvt_ctl_create_def(&wd, parent, limit)); } /////////////////////////////////////////////////////////// // TSlider_field /////////////////////////////////////////////////////////// void TSlider_field::set_window_data(const char* data) { TSlider_window& sw = (TSlider_window&)win(); const int sel = atoi(data); sw.set(sel); } const TString& TSlider_field::get_window_data() { TSlider_window& sw = (TSlider_window&)win(); TString& tmp = get_tmp_string(); tmp << sw.get(); return tmp; } void TSlider_field::set(const char* data) { if (!_range_min.is_zero()) { real n(data); n -= _range_min; data = n.string(); } set_window_data(data); set_dirty(); } const TString& TSlider_field::get() const { TString& str = (TString&)((TSlider_field*)this)->get_window_data(); if (!_range_min.is_zero()) { real n(str); n += _range_min; str = n.string(); } return str; } const char* TSlider_field::get_buddy() const { if (_buddy > 0) { const int pos = mask().id2pos(_buddy); if (pos > 0) { real n = mask().fld(pos).get(); if (n < _range_min) n = _range_min; if (n > _range_max) n = _range_max; return n.string(); } } return EMPTY_STRING; } void TSlider_field::set_buddy(const char* b) const { if (_buddy > 0) { const int pos = mask().id2pos(_buddy); if (pos > 0) mask().fld(pos).set(b); } } bool TSlider_field::on_hit() { if (!mask().is_running()) { set_range(_range_min, _range_max); // Imposto range dello slider const char* b = get_buddy(); if (b && *b) set(b); } return TWindowed_field::on_hit(); } word TSlider_field::class_id() const { return CLASS_SLIDER_FIELD; } bool TSlider_field::is_kind_of(word cid) const { return cid == CLASS_SLIDER_FIELD || TWindowed_field::is_kind_of(cid); } TField_window* TSlider_field::create_window(int x, int y, int dx, int dy, WINDOW parent) { return new TSlider_window(x, y, dx, dy, parent, this); } void TSlider_field::set_range(const real& mi, const real& ma) { _range_min = mi; _range_max = ma; set_range(mi.integer(), ma.integer()); } void TSlider_field::set_range(int mi, int ma) { _range_min = mi; _range_max = ma; if (_win != NULL_WIN) { TSlider_window& sw = (TSlider_window&)win(); sw.set_range(mi, ma); } } void TSlider_field::range(real& mi, real& ma) { mi = _range_min; ma = _range_max; } bool TSlider_field::parse_item(TScanner& scanner) { if (scanner.key() == "DR") // DRIVENBY id { _buddy = scanner.integer(); return true; } if (scanner.key() == "RA") // RANGE min max { const int mi = scanner.integer(); const int ma = scanner.integer(); set_range(mi, ma); return true; } return TWindowed_field::parse_item(scanner); } TSlider_field::TSlider_field(TMask* m) : TWindowed_field(m), _buddy(0), _range_min(ZERO), _range_max(CENTO) { } /////////////////////////////////////////////////////////// // TProp_window /////////////////////////////////////////////////////////// class TProp_window : public TField_window { public: TProp_window(int x, int y, int dx, int dy, WINDOW parent, TProp_field* owner); }; TProp_window::TProp_window(int x, int y, int dx, int dy, WINDOW parent, TProp_field* owner) : TField_window(0, 0, 0, 0, NULL, NULL) { XVT_COLOR_COMPONENT xcc[8]; memset(xcc, 0, sizeof(xcc)); xcc[0].type = XVT_COLOR_BACKGROUND; xcc[0].color = NORMAL_BACK_COLOR; xcc[1].type = XVT_COLOR_FOREGROUND; xcc[1].color = NORMAL_COLOR; xcc[2].type = XVT_COLOR_HIGHLIGHT; xcc[2].color = FOCUS_BACK_COLOR; xcc[3].type = XVT_COLOR_SELECT; xcc[3].color = FOCUS_COLOR; xcc[4].type = XVT_COLOR_BLEND; xcc[4].color = MASK_BACK_COLOR; xcc[5].type = XVT_COLOR_TROUGH; xcc[5].color = DISABLED_BACK_COLOR; xcc[6].type = XVT_COLOR_CAPTIONTEXT; xcc[6].color = PROMPT_COLOR; set_owner(owner); WIN_DEF wd; memset(&wd, 0, sizeof(wd)); wd.rct = resize_rect(x, y, dx, dy, wd.wtype, parent); wd.wtype = WC_PROPGRID; wd.ctlcolors = xcc; wd.v.ctl.ctrl_id = owner->dlg(); set_win(xvt_ctl_create_def(&wd, parent, 0L)); } word TProp_field::class_id() const { return CLASS_PROP_FIELD; } bool TProp_field::is_kind_of(word cid) const { return cid == CLASS_PROP_FIELD || TWindowed_field::is_kind_of(cid); } void TProp_field::freeze(bool on) { WINDOW pg = win().win(); if (on) xvt_prop_suspend(pg); else xvt_prop_restart(pg); } bool TProp_field::set_property(const char* name, const char* value, const char* label) { XVT_TREEVIEW_NODE node = NULL; WINDOW pg = win().win(); if (pg != NULL_WIN) { if (name != NULL && value == NULL && label != NULL) node = xvt_prop_add(pg, NULL, name, NULL, label); // Category! else { if (label && *label) node = xvt_prop_add(pg, "string", name, value, label); // Add property else { node = xvt_prop_find(win().win(), name); if (node) xvt_prop_set_data(pg, node, value); // Set property } } } return node != NULL; } bool TProp_field::set_property(const char* name, long value, const char* label) { bool done = false; TString16 str; str << value; if (label && *label) done = xvt_prop_add(win().win(), "long", name, str, label) != NULL; else done = set_property(name, str, label); return done; } bool TProp_field::set_property(const char* name, COLOR c, const char* label) { bool done = false; TString16 str; str.format("%d,%d,%d", XVT_COLOR_GET_RED(c), XVT_COLOR_GET_GREEN(c), XVT_COLOR_GET_BLUE(c)); if (label && *label) done = xvt_prop_add(win().win(), "color", name, str, label) != NULL; else done = set_property(name, str, label); return done; } bool TProp_field::set_property(const char* name, bool value, const char* label) { bool done = false; const TFixed_string str(value ? "True" : "False"); if (label && *label) done = xvt_prop_add(win().win(), "bool", name, str, label) != NULL; else done = set_property(name, str, label); return done; } bool TProp_field::has_property(const char* name) const { return xvt_prop_find(win().win(), name) != NULL; } bool TProp_field::enable_property(const char* name, bool on) { WINDOW pg = win().win(); XVT_TREEVIEW_NODE node = xvt_prop_find(pg, name); if (node != NULL) xvt_prop_set_read_only(pg, node, !on); return node != NULL; } bool TProp_field::remove_property(const char* name) { WINDOW pg = win().win(); XVT_TREEVIEW_NODE node = xvt_prop_find(pg, name); if (node != NULL) xvt_prop_remove(pg, node); return node != NULL; } const TString& TProp_field::get_property(const char* name) const { WINDOW pg = win().win(); XVT_TREEVIEW_NODE node = xvt_prop_find(pg, name); if (node) { TString& tmp = get_tmp_string(); const int len = xvt_prop_get_data(pg, node, tmp.get_buffer(), tmp.size()); if (len > tmp.size()) xvt_prop_get_data(pg, node, tmp.get_buffer(len), len); return tmp; } return EMPTY_STRING; } long TProp_field::get_long_property(const char* name) const { return atol(get_property(name)); } bool TProp_field::get_bool_property(const char* name) const { return strchr("1TXY", get_property(name)[0]) != NULL; } COLOR TProp_field::get_color_property(const char* name) const { COLOR col = COLOR_INVALID; const TString& tmp = get_property(name); if (tmp.full()) { int r = 0, g = 0, b = 0; if (sscanf(tmp, "%d,%d,%d", &r, &g, &b) == 3) col = RGB2COLOR(r,g,b); else col = r ? r : COLOR_BLACK; } return col; } bool TProp_field::get_var_property(const char* name, TVariant& var) const { WINDOW pg = win().win(); XVT_TREEVIEW_NODE node = xvt_prop_find(pg, name); if (node) { TString8 type; xvt_prop_get_type(pg, node, type.get_buffer(), type.size()); TString tmp; const int len = xvt_prop_get_data(pg, node, tmp.get_buffer(), tmp.size()); if (len > tmp.size()) xvt_prop_get_data(pg, node, tmp.get_buffer(len), len); switch (toupper(type[0])) { case 'B': var.set(tmp.full() && strchr("1TXY", tmp[0]) != NULL); break; case 'I': case 'L': var.set(atol(tmp)); break; default : var.set(tmp); break; } return true; } var.set_null(); return false; } bool TProp_field::current_property(TString& name, TVariant& value) const { name.cut(0); value.set_null(); WINDOW pg = win().win(); if (pg != NULL_WIN) { XVT_TREEVIEW_NODE node = xvt_prop_current(pg); if (node != NULL) { TFilename n; xvt_prop_get_string(pg, node, n.get_buffer(), n.size()); name = n; xvt_prop_get_data(pg, node, n.get_buffer(), n.size()); if (real::is_natural(n)) value = atol(n); else value = n; } } return !value.is_null(); } bool TProp_field::for_each_property(PROP_CALLBACK pcb, void* jolly) { return xvt_prop_for_each(win().win(), pcb, jolly) != 0; } bool TProp_field::parse_item(TScanner& scanner) { if (scanner.key() == "IT") { const TString80 label = dictionary_translate(scanner.string()); TString16 type = scanner.pop(); TString80 name, value; if (type.starts_with("IT")) { type.cut(0); scanner.push(); } else { const TString& line = scanner.line(); int equal = line.find('='); if (equal < 0) equal = line.find(' '); if (equal > 0) { name = line.left(equal); name.trim(); value = line.mid(equal+1); value.trim(); if (value[0] == '"') { value.rtrim(1); value.ltrim(1); } } else { name.trim(); value.cut(0); } type.cut(2); } TToken_string* item = new TToken_string; item->add(type); item->add(name); item->add(value); item->add(label,3); _items.add(item); return true; } return TWindowed_field::parse_item(scanner); } TField_window* TProp_field::create_window(int x, int y, int dx, int dy, WINDOW parent) { TProp_window* pw = new TProp_window(x, y, dx, dy, parent, this); if (!_items.empty()) { WINDOW pg = pw->win(); xvt_prop_suspend(pg); TString8 type; TString80 name, value, label; FOR_EACH_ARRAY_ROW(_items, i, row) { row->get(0, type); row->get(1, name); row->get(2, value); row->get(3, label); if (type.full()) { if (type == "BO") xvt_prop_add(pg, "bool", name, value, label); else if (type == "CO") xvt_prop_add(pg, "color", name, value, label); else if (type == "NU" || type == "CU") xvt_prop_add(pg, "long", name, value, label); else xvt_prop_add(pg, "string", name, value, label); } else xvt_prop_add(pg, "", "", "", label); } xvt_prop_fit_columns(pg); xvt_prop_restart(pg); _items.destroy(); } return pw; } TProp_field::TProp_field(TMask* m) : TWindowed_field(m) { _items.destroy(); } /////////////////////////////////////////////////////////// // TTreelist_window /////////////////////////////////////////////////////////// class TTreelist_window : public TTree_window { TAuto_token_string _fields; private: virtual void create_children(XVT_TREEVIEW_NODE node); virtual void handle_tree_event(EVENT* ep); virtual bool add_child(XVT_TREEVIEW_NODE parent); protected: virtual long handler(WINDOW win, EVENT* ep); bool get_fields(TToken_string& csv); public: virtual bool select_current(); virtual bool goto_selected(); virtual void set_header(const char* head); virtual void set_fields(const char* flds); virtual void force_update(); TTreelist_window(int x, int y, int dx, int dy, WINDOW parent, TTreelist_field* owner); virtual ~TTreelist_window() { } }; bool TTreelist_window::get_fields(TToken_string& csv) { if (_fields.empty_items()) return tree()->get_description(csv); csv.cut(0); TVariant var; FOR_EACH_TOKEN(_fields, str) { var.set_null(); tree()->get_var(str, var); if (var.is_empty()) csv.add(" "); else csv.add(var.as_string()); } return true; } bool TTreelist_window::add_child(XVT_TREEVIEW_NODE parent) { XVT_TREEVIEW_NODE_TYPE type = tree()->could_have_son() ? XVT_TREEVIEW_NODE_NONTERMINAL : XVT_TREEVIEW_NODE_TERMINAL; XVT_IMAGE ii = NULL, ic = NULL, ie = NULL; TImage* im_nor = tree()->image(false); if (im_nor != NULL) { 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(); } TToken_string csv(80, '\t'); get_fields(csv); TString256 id; tree()->curr_id(id); XVT_TREEVIEW_NODE child = xvt_treelist_add_child_node(_ctrl, parent, type, ii, ic, ie, csv, NULL, id); if (child != NULL) { if (!tree()->enabled()) xvt_treelist_enable_node(_ctrl, child, FALSE); if (tree()->marked()) xvt_treelist_set_node_bold(_ctrl, child, TRUE); if (type == XVT_TREEVIEW_NODE_NONTERMINAL && tree()->expanded()) { for (bool ok = tree()->goto_firstson(); ok; ok = tree()->goto_rbrother()) add_child(child); xvt_treelist_expand_node(_ctrl, child, FALSE); } } tree()->goto_node(id); return true; } void TTreelist_window::create_children(XVT_TREEVIEW_NODE node) { bool ok = false; TString id; if (tree() != NULL) { if (node != NULL) id = xvt_treelist_get_node_data(_ctrl, node); if (id.empty()) // Sono sulla radice { node = xvt_treelist_get_root_node(_ctrl); ok = tree()->goto_root(); } else { tree()->goto_node(id); ok = tree()->goto_firstson(); } } xvt_treelist_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 TTreelist_window::handle_tree_event(EVENT* ep) { XVT_TREEVIEW_NODE node = ep->v.ctl.ci.v.treeview.node; if (node == NULL) // Click fuori da tutto { if (ep->v.ctl.ci.v.treeview.dbl_click) owner().on_key(K_F11); else if (ep->v.ctl.ci.v.treeview.sgl_click) owner().on_key(K_F8); return; } const TString id = (const char*)xvt_treelist_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_treelist_set_node_images(_ctrl, node, ii, ic, ie); TToken_string csv(80, '\t'); get_fields(csv); xvt_treelist_set_node_string(_ctrl, node, csv); } } 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; } } } } long TTreelist_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_CONTROL: if (ep->v.ctl.ci.type == WC_TREELIST && tree() != NULL) { handle_tree_event(ep); return 0L; } break; case E_UPDATE: return 0L; default: break; } return TControl_host_window::handler(win, ep); } bool TTreelist_window::select_current() { XVT_TREEVIEW_NODE nextsel = NULL; // Nodo da selezionare (se mai lo trovero') if (tree() != NULL) { 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_treelist_get_selected_node(_ctrl); nextsel = xvt_treelist_find_node_string(_ctrl, id); if (nextsel != NULL && cursel == nextsel) return true; if (nextsel == NULL) { xvt_treelist_suspend(_ctrl); // Sospendo le notifiche degli eventi 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_treelist_get_child_node(_ctrl, parent, i); if (child == NULL && i == 0) // Forse non c'e' nessun figlio ... { create_children(parent); // ... sara' vero? child = xvt_treelist_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_treelist_get_node_data(_ctrl, child); if (*row == data) { nextsel = child; if (*row == id) // Ho finito killed = true; else { parent = child; xvt_treelist_expand_node(_ctrl, child, FALSE); } break; } } } xvt_treelist_resume(_ctrl); // Riattivo le notifiche degli eventi tree()->goto_node(id); // Riposiziono l'albero } if (nextsel != NULL) { xvt_treelist_select_node(_ctrl, nextsel, TRUE); if (tree()->expanded()) xvt_treelist_expand_node(_ctrl, nextsel, FALSE); } } return nextsel != NULL; } bool TTreelist_window::goto_selected() { bool ok = false; XVT_TREEVIEW_NODE child = xvt_treelist_get_selected_node(_ctrl); if (child != NULL) { const char* data = (const char*)xvt_treelist_get_node_data(_ctrl, child); ok = tree()->goto_node(data); } return ok; } void TTreelist_window::set_header(const char* head) { _header = head; xvt_treelist_set_node_string(_ctrl, NULL, _header); } void TTreelist_window::set_fields(const char* field) { _fields = field; } TTreelist_window::TTreelist_window(int x, int y, int dx, int dy, WINDOW parent, TTreelist_field* owner) : TTree_window(x, y, dx, dy, parent, owner) { XVT_COLOR_COMPONENT xcc[8]; memset(xcc, 0, sizeof(xcc)); xcc[0].type = XVT_COLOR_BACKGROUND; xcc[0].color = NORMAL_BACK_COLOR; xcc[1].type = XVT_COLOR_FOREGROUND; xcc[1].color = NORMAL_COLOR; xcc[2].type = XVT_COLOR_HIGHLIGHT; xcc[2].color = FOCUS_BACK_COLOR; xcc[3].type = XVT_COLOR_SELECT; xcc[3].color = FOCUS_COLOR; xcc[4].type = XVT_COLOR_BLEND; xcc[4].color = MASK_BACK_COLOR; xcc[5].type = XVT_COLOR_TROUGH; xcc[5].color = DISABLED_COLOR; WIN_DEF wd[2]; memset(&wd, 0, sizeof(wd)); wd->wtype = WC_TREELIST; wd->v.ctl.ctrl_id = owner->dlg(); wd->v.ctl.font_id = xvtil_default_font(); xvt_vobj_get_client_rect(win(), &wd->rct); wd->ctlcolors = xcc; _ctrl = xvt_ctl_create_def(wd, win(), (long)this); if (!_items.empty()) { TToken_string header(80, '\t'); TToken_string fields(80, '\t'); FOR_EACH_ARRAY_ROW(_items, i, text) { header.add(text->get(0)); fields.add(text->get()); } set_header(header); set_fields(fields); _items.destroy(); } } void TTreelist_window::force_update() { TTree_window::force_update(); xvt_dwin_invalidate_rect(_ctrl, NULL); } /////////////////////////////////////////////////////////// // TTreelist_field /////////////////////////////////////////////////////////// word TTreelist_field::class_id() const { return CLASS_TREELIST_FIELD; } bool TTreelist_field::is_kind_of(word cid) const { return cid == CLASS_TREELIST_FIELD || TTree_field::is_kind_of(cid); } bool TTreelist_field::parse_item(TScanner& scanner) { if (scanner.key() == "DI") // Encouraged syntax: DISPLAY "Header@10" FieldName { const TString80 label = dictionary_translate_header(scanner.string()); TString80 fld = scanner.line(); fld.strip(" '\""); TToken_string* item = new TToken_string(80, '\t'); item->add(label); item->add(fld); _items.add(item); return true; } return TTree_field::parse_item(scanner); } TField_window* TTreelist_field::create_window(int x, int y, int dx, int dy, WINDOW parent) { return new TTreelist_window(x, y, dx, dy, parent, this); } TTreelist_field::TTreelist_field(TMask* m) : TTree_field(m) { _items.destroy(); }