#include #include #include #include #include "ba8300.h" #include "ba8301.h" /////////////////////////////////////////////////////////// // TReport_tree /////////////////////////////////////////////////////////// bool TReport_tree::get_description(TString& str) const { str.cut(0); switch (_curr[0]) { case 'H': str << " " << TR("Testa"); break; case 'B': str << " " << TR("Corpo"); break; case 'F': str << " " << TR("Coda"); break; case 'P': str << TR("Pagina"); break; // Virtual section case 'R': str << TR("Report"); break; // Virtual section case 'S': str << TR("Speciali"); break; // Virtual section default : break; } if (_curr[1] > '0') str << ' ' << _curr[1]; return true; } bool TReport_tree::goto_node(char type, int level) { const bool ok = type > ' ' && level >= 0; if (ok) _curr.format("%c%d", type, level); return ok; } void TReport_tree::node2id(const TObject* node, TString& id) const { id = *(TString*)node; } TReport_section& TReport_tree::curr_section() const { char type = _curr[0]; const int level = _curr[1]-'0'; if (type == 'R' || type == 'P') type = 'B'; return _report.section(type, level); } bool TReport_tree::goto_root() { return goto_node('P', 0); } bool TReport_tree::goto_firstson() { char ntype = 'H'; int nlevel = -1; switch (_curr[0]) { case 'P': nlevel = 0; break; case 'R': nlevel = _report.find_max_level('H'); break; case 'S': if (_report.find_section('B',2) != NULL) { ntype = 'B'; nlevel = 2; } break; default : break; } return goto_node(ntype, nlevel); } bool TReport_tree::goto_rbrother() { const char type = _curr[0]; const int level = _curr[1]-'0'; char ntype = ' '; int nlevel = -1; if (level <= 0) // Page { switch (type) { case 'H': ntype = 'B'; break; case 'B': ntype = 'F'; break; case 'P': ntype = 'R'; break; case 'R': ntype = 'S'; break; default : break; } nlevel = level; } else // Report { switch (type) { case 'H': if (level > 1) { ntype = type; nlevel = level-1; } else { ntype = 'B'; nlevel = 1; } break; case 'B': ntype = 'F'; nlevel = 1; break; case 'F': if (level < _report.find_max_level('F')) { ntype = 'F'; nlevel = level+1; } break; default: break; } } return goto_node(ntype, nlevel); } bool TReport_tree::goto_node(const TString &id) { return goto_node(id[0], id[1]-'0'); } bool TReport_tree::has_son() const { bool yes = false; switch (_curr[0]) { case 'P': case 'R': yes = true; break; case 'S': yes = _report.find_section('B', 2) != NULL; break; default: break; } return yes; } bool TReport_tree::has_rbrother() const { const TString4 old = _curr; TReport_tree* myself = (TReport_tree*)this; const bool ok = myself->goto_rbrother(); myself->_curr = old; return ok; } bool TReport_tree::has_root() const { return true; // In realta' ci sono 3 root: Pagina, Report, Speciali } bool TReport_tree::has_father() const { return !has_son(); } bool TReport_tree::goto_father() { bool yes = has_father(); if (yes) { char ntype = ' '; if (_curr[1] == '0') ntype = 'P'; else { if (_curr[0] == 'B' && _curr[1] > '1') ntype = 'S'; else ntype = 'R'; } yes = goto_node(ntype, 0); } return yes; } bool TReport_tree::has_lbrother() const { const TString4 old = _curr; TReport_tree* myself = (TReport_tree*)this; const bool ok = myself->goto_lbrother(); myself->_curr = old; return ok; } bool TReport_tree::goto_lbrother() { const char type = _curr[0]; const int level = _curr[1]-'0'; char ntype = ' '; int nlevel = -1; if (level == 0) // Page { switch (type) { case 'B': ntype = 'H'; break; case 'F': ntype = 'B'; break; case 'R': ntype = 'P'; break; case 'S': ntype = 'R'; break; default : break; } nlevel = level; } else // Report { switch (type) { case 'F': if (level > 1) { ntype = type; nlevel = level-1; } else { ntype = 'B'; nlevel = 1; } break; case 'B': ntype = 'H'; nlevel = 1; break; case 'H': if (level < _report.find_max_level('H')) { ntype = 'H'; nlevel = level+1; } break; default: break; } } return goto_node(ntype, nlevel); } TImage* TReport_tree::image(bool selected) const { int id = 0; switch (_curr[0]) { case 'H': id = 1810; break; case 'B': id = 1811; break; case 'F': id = 1812; break; default : break; } if (id > 0) return get_res_image(id); return TTree::image(selected); } int TReport_tree::image_height() const { const TImage* img = image(false); return img != NULL ? img->height() : 0; } /////////////////////////////////////////////////////////// // TReport_window /////////////////////////////////////////////////////////// class TReport_window : public TField_window { TReport* _report; PNT _dpi; int _dragging; TPoint _pt_drag_start; PNT _pt_drag_offset; RCT _rct_drag; TArray _clipboard; protected: virtual void handler(WINDOW win, EVENT* ep); virtual void update(); virtual bool on_key(KEY k); protected: void draw_square(int x, int y, int s); void draw_field(const TReport_field& f); void draw_grid(); void draw_fields(); void snap_drag(PNT& pnt) const; void draw_dragster(); void popup_menu(EVENT* ep); void popup_cut(); void popup_copy(); void popup_paste(); int cpi() const; int lpi() const; public: virtual PNT log2dev(long x, long y) const; virtual TPoint dev2log(const PNT& pt) const; void log2dev(const RCT& rctlog, RCT& rctdev) const; void dev2log(const RCT& rctdev, RCT& rctlog) const; TReport_section& curr_section() const; bool get_selection_rect(RCT& rct) const; bool pick(const TPoint& ptlog) const; void clear_selection(); void select(const RCT& rct); void offset_selection(const TPoint& p); void set_report(TReport* rep) { _report = rep; } TReport_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner); virtual ~TReport_window() { } }; TReport_section& TReport_window::curr_section() const { TMask& m = owner().mask(); TTree_field& sections = m.tfield(F_SECTIONS); sections.goto_selected(); TReport_tree& tree = *(TReport_tree*)sections.tree(); return tree.curr_section(); } void TReport_window::draw_square(int x, int y, int s) { RCT rct; rct.left = x; rct.top = y; rct.right = x+s; rct.bottom = y+s; xvt_dwin_draw_rect(win(), &rct); } void TReport_window::draw_field(const TReport_field& f) { RCT r; f.get_rect(r); log2dev(r, r); switch (f.type()) { case 'D': case 'N': case 'S': case 'T': if (f.border() <= 0) { set_pen(COLOR_LTGRAY); set_brush(f.back_color(), PAT_NONE); xvt_dwin_draw_rect(win(), &r); } f.draw(*this, rdm_edit); break; default: f.draw(*this, rdm_edit); break; } if (f.selected()) { set_pen(COLOR_BLACK); set_brush(COLOR_BLACK); const int s = 5; draw_square(r.left, r.top, s); draw_square(r.right-s, r.bottom-s, s); } } void TReport_window::draw_fields() { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { const TReport_field& f = *(const TReport_field*)o; draw_field(f); } } bool TReport_window::pick(const TPoint& ptlog) const { TReport_section& rs = curr_section(); RCT rct; const PNT pt = { short(ptlog.y), short(ptlog.x) }; FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; f.get_rect(rct); if (xvt_rect_has_point(&rct, pt)) { f.select(); return true; } } return false; } void TReport_window::clear_selection() { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field* f = (TReport_field*)o; f->select(false); } } bool TReport_window::get_selection_rect(RCT& rct) const { TReport_section& rs = curr_section(); bool full = false; FOR_EACH_ARRAY_ITEM(rs, i, o) { const TReport_field& f = *(const TReport_field*)o; if (f.selected()) { if (!full) { f.get_rect(rct); full = true; } else { RCT r; f.get_rect(r); if (r.left < rct.left) rct.left = r.left; if (r.right > rct.right) rct.right = r.right; if (r.top < rct.top) rct.top = r.top; if (r.bottom > rct.bottom) rct.bottom = r.bottom; } } } return full; } void TReport_window::offset_selection(const TPoint& p) { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; if (f.selected()) f.offset(p); } } void TReport_window::select(const RCT& rct) { clear_selection(); TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; RCT r; f.get_rect(r); if (xvt_rect_intersect(NULL, (RCT*)&rct, &r)) f.select(); } } void TReport_window::draw_dragster() { set_mode(M_XOR); set_pen(COLOR_CYAN); set_brush(COLOR_WHITE, PAT_NONE); xvt_dwin_draw_rect(win(), &_rct_drag); set_mode(M_COPY); } void TReport_window::snap_drag(PNT& pnt) const { const int kx = _dpi.h / cpi(); const int ky = _dpi.v / lpi(); pnt.h = (pnt.h / kx) * kx; pnt.v = (pnt.v / ky) * ky; } bool TReport_window::on_key(KEY k) { switch (k) { case K_ENTER: owner().mask().send_key(K_SPACE, F_FLD_PROPERTIES); break; case K_ESC: { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; if (f.selected()) f.select(false); } force_update(); } break; default: break; } return TField_window::on_key(k); } #define POPUP_CUT 20883 #define POPUP_COPY 20884 #define POPUP_PASTE 20885 #define POPUP_DUP 20886 #define POPUP_CLEAR 20887 #define POPUP_PROPERTIES 20888 void TReport_window::popup_menu(EVENT* ep) { MENU_ITEM menu[8]; memset(menu, 0, sizeof(menu)); RCT rct; const bool sel = get_selection_rect(rct); const bool clp = _clipboard.items() > 0; menu[0].tag = POPUP_CUT; menu[0].text = "Taglia"; menu[0].enabled = sel; menu[1].tag = POPUP_COPY; menu[1].text = "Copia"; menu[1].enabled = sel; menu[2].tag = POPUP_PASTE; menu[2].text = "Incolla"; menu[2].enabled = clp; menu[3].tag = POPUP_DUP; menu[3].text = "Duplica"; menu[3].enabled = sel; menu[4].tag = POPUP_CLEAR; menu[4].text = "Cancella"; menu[4].enabled = sel; menu[5].tag = -1; menu[5].separator = true; menu[6].tag = POPUP_PROPERTIES; menu[6].text = "Proprieta'"; menu[6].enabled = true; const PNT& p = ep->v.mouse.where; _pt_drag_start = dev2log(p); xvt_menu_popup(menu, win(), p, XVT_POPUP_CENTER, 0); } void TReport_window::popup_cut() { _clipboard.destroy(); TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM_BACK(rs, i, o) { TReport_field& f = *(TReport_field*)o; if (f.selected()) { TObject* obj = rs.remove(i, true); _clipboard.add(obj); } } force_update(); } void TReport_window::popup_copy() { _clipboard.destroy(); TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; if (f.selected()) _clipboard.add(f); } } void TReport_window::popup_paste() { if (_clipboard.items() > 0) { RCT rct; ((TReport_field&)_clipboard[0]).get_rect(rct); const TPoint off(_pt_drag_start.x-rct.left, _pt_drag_start.y-rct.top); clear_selection(); TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(_clipboard, i, o) { TReport_field& f = *(TReport_field*)o; f.set_section(&rs); f.select(); f.offset(off); rs.add(f); } force_update(); } } void TReport_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_MOUSE_DOWN: if (ep->v.mouse.button == 0) { const TPoint pt = dev2log(ep->v.mouse.where); const PNT p = { short(pt.y), short(pt.x) }; RCT rct; bool full = get_selection_rect(rct); if (!full || !xvt_rect_has_point(&rct, p)) { if (full) clear_selection(); pick(pt); full = get_selection_rect(rct); } if (full) { log2dev(rct, _rct_drag); _pt_drag_offset.h = ep->v.mouse.where.h - _rct_drag.left; _pt_drag_offset.v = ep->v.mouse.where.v - _rct_drag.top; _dragging = 2; XinCursor hand = xi_get_pref(XI_PREF_HAND_CURSOR_RID); xvt_win_set_cursor(win, (CURSOR)hand); } else { const PNT& pnt = ep->v.mouse.where; xvt_rect_set(&_rct_drag, pnt.h, pnt.v, pnt.h, pnt.v); _dragging = 1; } _pt_drag_start.x = rct.left; _pt_drag_start.y = rct.top; draw_dragster(); xvt_win_trap_pointer(win); } else { popup_menu(ep); } break; case E_MOUSE_MOVE: { TMask& m = owner().mask(); const TPoint p = dev2log(ep->v.mouse.where); m.set(F_X, p.x/100); m.set(F_Y, p.y/100); if (_dragging != 0) { draw_dragster(); PNT pt = ep->v.mouse.where; switch (_dragging) { case 1: _rct_drag.right = pt.h; _rct_drag.bottom = pt.v; break; case 2: pt.h -= _pt_drag_offset.h; pt.v -= _pt_drag_offset.v; if (!ep->v.mouse.shift) snap_drag(pt); xvt_rect_set_pos(&_rct_drag, pt); break; default: break; } draw_dragster(); } } break; case E_MOUSE_UP: if (_dragging != 0) { draw_dragster(); PNT pt = ep->v.mouse.where; switch (_dragging) { case 1: { _rct_drag.right = pt.h; _rct_drag.bottom = pt.v; RCT rct; dev2log(_rct_drag, rct); select(rct); } break; case 2: { pt.h -= _pt_drag_offset.h; pt.v -= _pt_drag_offset.v; if (!ep->v.mouse.shift) snap_drag(pt); TPoint offset = dev2log(pt); offset.x -= _pt_drag_start.x; offset.y -= _pt_drag_start.y; offset_selection(offset); } break; default: break; } force_update(); _dragging = 0; xvt_win_release_pointer(); xvt_win_set_cursor(win, CURSOR_ARROW); } break; case E_MOUSE_DBL: owner().mask().send_key(K_SPACE, F_FLD_PROPERTIES); break; case E_COMMAND: switch(ep->v.cmd.tag) { case POPUP_CUT: case POPUP_CLEAR: popup_cut(); break; case POPUP_COPY: popup_copy(); break; case POPUP_PASTE: popup_paste(); break; case POPUP_DUP: popup_copy(); popup_paste(); break; case POPUP_PROPERTIES: { clear_selection(); const bool full = pick(_pt_drag_start); if (full) owner().mask().send_key(K_SPACE, F_FLD_PROPERTIES); else owner().mask().send_key(K_SPACE, F_SEC_PROPERTIES); } break; default: break; } break; default: break; } TField_window::handler(win, ep); } PNT TReport_window::log2dev(long x, long y) const { x -= origin().x*100; y -= origin().y*100; PNT p; p.h = short((x * _dpi.h) / (cpi() * 100L)); p.v = short((y * _dpi.v) / (lpi() * 100L)); return p; } TPoint TReport_window::dev2log(const PNT& pt) const { TPoint p; p.x = pt.h * 100L * cpi() / _dpi.h; p.y = pt.v * 100L * lpi() / _dpi.v; p.x += origin().x * 100L; p.y += origin().y * 100L; return p; } void TReport_window::log2dev(const RCT& rctlog, RCT& rctdev) const { const PNT f = log2dev(rctlog.left, rctlog.top); const PNT t = log2dev(rctlog.right, rctlog.bottom); rctdev.left = f.h; rctdev.top = f.v; rctdev.right = t.h; rctdev.bottom = t.v; } void TReport_window::dev2log(const RCT& rctdev, RCT& rctlog) const { const PNT pf = { rctdev.top, rctdev.left }; const PNT pt = { rctdev.bottom, rctdev.right }; const TPoint f = dev2log(pf); const TPoint t = dev2log(pt); rctlog.left = short(f.x); rctlog.top = short(f.y); rctlog.right = short(t.x); rctlog.bottom = short(t.y); } void TReport_window::draw_grid() { clear(COLOR_WHITE); set_pen(MAKE_COLOR(232,232,232)); RCT rct; xvt_vobj_get_client_rect(win(), &rct); const int max = 192; const int k = 100; for (int i = 1; i < max; i++) { line(0, i*k, max*k, i*k); line(i*k, 0, i*k, max*k); } } void TReport_window::update() { draw_grid(); draw_fields(); } int TReport_window::cpi() const { return _report ? _report->cpi() : 12; } int TReport_window::lpi() const { return _report ? _report->lpi() : 6; } TReport_window::TReport_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner) : TField_window(x, y, dx, dy, parent, owner), _dragging(0), _report(NULL) { _dpi.h = _dpi.v = 96; _pixmap = true; set_scroll_max(196,196); } /////////////////////////////////////////////////////////// // TReport_drawer /////////////////////////////////////////////////////////// TField_window* TReport_drawer::create_window(int x, int y, int dx, int dy, WINDOW parent) { return new TReport_window(x, y, dx, dy, parent, this); } void TReport_drawer::set_report(TReport* rep) { TReport_window* w = (TReport_window*)_win; w->set_report(rep); }