#include #include #include #include #include #include #include #include #include #include #include #include "ba8201.h" #include "ba8300.h" #include "ba8301.h" #include /////////////////////////////////////////////////////////// // TReport_tree /////////////////////////////////////////////////////////// class TReport_tree : public TBidirectional_tree { TReport& _report; TString4 _curr; protected: virtual bool get_description(TString& str) const; virtual TImage* image(bool selected) const; virtual void node2id(const TObject* node, TString& id) const; public: virtual bool goto_root(); virtual bool goto_firstson(); virtual bool goto_rbrother(); virtual bool goto_node(const TString &id); virtual bool has_son() const; virtual bool has_rbrother() const; virtual TObject* curr_node() const { return (TObject*)&_curr; } virtual bool has_root() const; virtual bool has_father() const; virtual bool has_lbrother() const; virtual bool goto_father(); virtual bool goto_lbrother(); TReport_section& curr_section() const; bool goto_node(char type, int level); int image_height() const; TReport_tree(TReport& r) : _report(r) { goto_root(); } }; 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 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() { int nlevel = -1; switch (_curr[0]) { case 'P': nlevel = 0; break; case 'R': nlevel = _report.find_max_level(); break; default : break; } return goto_node('H', 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; 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()) { 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 { const char type = _curr[0]; return type == 'P' || type == 'R'; } 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; } bool TReport_tree::has_father() const { return !has_son(); } bool TReport_tree::goto_father() { return has_father() && goto_node(_curr[1] == '0' ? 'P' : 'R', 0); } 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 { if (type == 'B') ntype = 'H'; else if (type == 'F') ntype = 'B'; else if (type == 'R') ntype = 'P'; } 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()) { ntype = 'F'; 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_text(*this, f.picture()); break; default : f.draw(*this); 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); } class TReport_drawer : public TWindowed_field { protected: virtual TField_window* create_window(int x, int y, int dx, int dy, WINDOW parent); public: void set_report(TReport* rep); TReport_drawer(TMask* m) : TWindowed_field(m) { } }; 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); } /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// const TString& num2str(int num) { static TString8 _str; const real n(num / 100.0); _str = n.stringa(0, 2); const int comma = _str.find(','); if (comma > 0) { if (_str[comma+2] == '0') { if (_str[comma+1] == '0') _str.cut(comma); else _str.cut(comma+2); } } return _str; } /////////////////////////////////////////////////////////// // TReport_field_mask /////////////////////////////////////////////////////////// class TReport_field_mask : public TAutomask { COLOR _fgcolor, _bgcolor; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); virtual void handler(WINDOW win, EVENT* ep); public: void set_num(short id, short n); short get_num(short id) const; void set_field(const TReport_field& rf); void get_field(TReport_field& rf) const; TReport_field_mask() :TAutomask("ba8300b") { } }; void TReport_field_mask::set_num(short id, short num) { set(id, num2str(num)); } short TReport_field_mask::get_num(short id) const { TString8 str = get(id); str.replace(',', '.'); real n(str); n *= CENTO; return (short)n.integer(); } void TReport_field_mask::handler(WINDOW win, EVENT* ep) { if (ep->type == E_UPDATE) { for (int i = 0; i < 2; i++) { RCT rct; field(i == 0 ? F_FGCOLOR : F_BGCOLOR).get_rect(rct); xvt_rect_offset(&rct, rct.right-rct.left + 4*CHARX, 0); xi_draw_3d_rect((XinWindow)win, (XinRect*)&rct, TRUE, 2, MASK_LIGHT_COLOR, i == 0 ? _fgcolor : _bgcolor, MASK_DARK_COLOR); } } TAutomask::handler(win, ep); } bool TReport_field_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch(o.dlg()) { case F_X: case F_Y: case F_DX: case F_DY: if (e == fe_modify) { const int num = get_num(o.dlg()); set_num(o.dlg(), num); // Reformat } break; case F_FGCOLOR: if (e == fe_button) { _fgcolor = xvt_dm_post_choose_color(win(), _fgcolor); force_update(); } break; case F_BGCOLOR: if (e == fe_button) { _bgcolor = xvt_dm_post_choose_color(win(), _bgcolor); force_update(); } break; default: break; } return true; } void TReport_field_mask::set_field(const TReport_field& rf) { const char str[2] = { rf.type(), '\0' }; set(F_TYPE, str); RCT r; rf.get_rect(r); set_num(F_X, r.left); set_num(F_Y, r.top); set_num(F_DX, r.right-r.left); set_num(F_DY, r.bottom-r.top); set(F_HALIGN, rf.horizontal_alignment()); set(F_VALIGN, rf.vertical_alignment()); set(F_BORDER, rf.border()); _fgcolor = rf.fore_color(); _bgcolor = rf.back_color(); set(F_TEXT, rf.picture()); set(F_SOURCE, rf.field()); } void TReport_field_mask::get_field(TReport_field& rf) const { rf.set_type(get(F_TYPE)[0]); rf.set_pos(get_num(F_X), get_num(F_Y)); rf.set_size(get_num(F_DX), get_num(F_DY)); rf.set_horizontal_alignment(get(F_HALIGN)[0]); rf.set_vertical_alignment(get(F_VALIGN)[0]); rf.set_border(get_int(F_BORDER)); rf.set_fore_color(_fgcolor); rf.set_back_color(_bgcolor); rf.set_picture(get(F_TEXT)); rf.set_field(get(F_SOURCE)); } /////////////////////////////////////////////////////////// // TReport_sheet /////////////////////////////////////////////////////////// class TReport_sheet : public TSheet { TReport_section& _section; protected: virtual long get_items() const { return _section.items(); } virtual void get_row(long r, TToken_string& row); public: virtual KEY run(); int selection(int& first, int& last) const; TReport_sheet(TReport_section& sec); }; void TReport_sheet::get_row(long r, TToken_string& row) { const TReport_field& rf = (const TReport_field&)_section[r]; RCT rect; rf.get_rect(rect); row.cut(0); row.add(checked(r) ? "X" : " "); row.add(rf.type_name()); row.add(num2str(rect.top)); row.add(num2str(rect.left)); row.add(num2str(rect.right-rect.left)); row.add(num2str(rect.bottom-rect.top)); row.add(rf.picture()); row.add(rf.field()); } int TReport_sheet::selection(int& first, int& last) const { int tot = 0; first = items()+1; last = -1; FOR_EACH_ARRAY_ITEM_BACK(_section, i, o) { const TReport_field& rf = *(const TReport_field*)o; if (rf.selected()) { if (i < first) first = i; if (i > last) last = i; tot++; } } return tot; } KEY TReport_sheet::run() { int first = -1; uncheck(-1); FOR_EACH_ARRAY_ITEM(_section, i, o) { const TReport_field& rf = *(const TReport_field*)o; if (rf.selected()) { check(i); if (first < 0) first = i; } } if (first > 0) select(first); const KEY k = TSheet::run(); if (k != K_ESC) { FOR_EACH_ARRAY_ITEM(_section, i, o) { TReport_field& rf = *(TReport_field*)o; rf.select(checked(i)); } } return k; } TReport_sheet::TReport_sheet(TReport_section& sec) : TSheet(-1, -1, -2, -4, "Campi", "@1|Tipo@10|Riga@R|Col.@R|Larg.@R|Alt.@R|Testo@30|Campo@30", 0xE), _section(sec) { } /////////////////////////////////////////////////////////// // TReport_section_mask /////////////////////////////////////////////////////////// class TReport_section_mask : public TAutomask { XVT_FNTID _font; bool _font_changed; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void set_num(short id, short num); short get_num(short id) const; void vedo_non_vedo(); public: void set_section(const TReport_section& rs); void get_section(TReport_section& rs) const; TReport_section_mask() : TAutomask("ba8300c"), _font(NULL), _font_changed(false) { } }; void TReport_section_mask::set_num(short id, short num) { set(id, num2str(num)); } short TReport_section_mask::get_num(short id) const { TString8 str = get(id); str.replace(',', '.'); real n(str); n *= CENTO; return (short)n.integer(); } void TReport_section_mask::vedo_non_vedo() { const char type = get(F_TYPE)[0]; const int level = get_int(F_LEVEL); show(F_GROUP_BY, level > 1); show(F_HIDE_IF_NEEDED, level == 0 && type != 'B'); enable(DLG_DELREC, level > 1); } bool TReport_section_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch(o.dlg()) { case F_TYPE: case F_LEVEL: if (e == fe_modify) vedo_non_vedo(); break; case F_DX: case F_DY: if (e == fe_modify) { const int num = get_num(o.dlg()); set_num(o.dlg(), num); // Reformat } break; case F_FONT_SELECT: if (e == fe_button) { if (xvt_dm_post_font_sel(win(), _font, NULL, 0)) _font_changed = true; } break; default: break; } return true; } void TReport_section_mask::set_section(const TReport_section& rs) { char s[2] = { rs.type(), '\0' }; set(F_TYPE, s); set(F_LEVEL, rs.level()); set_num(F_DX, rs.width()); set_num(F_DY, rs.height()); set(F_GROUP_BY, rs.grouped_by()); set(F_HIDE_IF_NEEDED, rs.hidden_if_needed() ? "X" : ""); XVT_FNTID old_font = rs.font().get_xvt_font(*this); _font = xvt_font_create(); xvt_font_copy(_font, old_font, ~0); xvt_font_set_size(_font, rs.font().size()); vedo_non_vedo(); } void TReport_section_mask::get_section(TReport_section& rs) const { rs.set_width(get_num(F_DX)); rs.set_height(get_num(F_DY)); rs.group_by(get(F_GROUP_BY)); rs.hide_if_needed(get_bool(F_HIDE_IF_NEEDED)); if (_font_changed) { TString name; xvt_font_get_family(_font, name.get_buffer(), name.size()); const int size = xvt_font_get_size(_font); const XVT_FONT_STYLE_MASK style = xvt_font_get_style(_font); rs.set_font(name, size, style); } } /////////////////////////////////////////////////////////// // TReport_mask /////////////////////////////////////////////////////////// class TReport_mask : public TAutomask { TReport _report; TReport_tree _tree; TFilename _curr_report; bool _is_dirty; protected: virtual TMask_field* parse_field(TScanner& scanner); virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); protected: bool select_query(); bool select_report(); void update_report() const; TReport_section& curr_section(); void add_field(); void edit_field(TReport_field& rf); void fields_properties(); void section_properties(); void on_print(); bool get_rep_path(TFilename& path) const; void set_num_attr(TXmlItem& item, const char* attr, short num, short def = 0) const; void set_col_attr(TXmlItem& item, const char* attr, COLOR col, COLOR def) const; void save_section(const TReport_section& rs, TXmlItem& item) const; public: bool save_report(); bool save_if_needed(); void global_reset(); bool delete_report(); bool load_report(); TReport_tree& sections() { return _tree; } TReport_mask(); }; TMask_field* TReport_mask::parse_field(TScanner& scanner) { if (scanner.token().starts_with("RE")) return new TReport_drawer(this); return TAutomask::parse_field(scanner); } bool TReport_mask::select_report() { TFilename path; const bool ok = select_sql_file(path, "rep"); if (ok) { path = path.name(); path.ext(""); set(F_CODICE, path); } return ok; } bool TReport_mask::select_query() { TFilename path; bool ok = select_sql_file(path, "qry"); if (ok) { TXmlItem item; item.Load(path); const TXmlItem* sql = item.FindFirst("sql"); ok = sql != NULL; if (ok) { TString str; sql->GetEnclosedText(str); set(F_SQL, str, true); } } return ok; } bool TReport_mask::get_rep_path(TFilename& path) const { const TString& name = get(F_CODICE); const bool ok = name.not_empty(); if (ok) { get_sql_directory(path); path.add(name); path.ext("rep"); } return ok; } void TReport_mask::set_num_attr(TXmlItem& item, const char* attr, short num, short def) const { if (num != def) { const real n = (num / 100.0); item.SetAttr(attr, n.string()); } } void TReport_mask::set_col_attr(TXmlItem& item, const char* attr, COLOR col, COLOR def) const { if (color_distance(col, def) != 0) { TString16 str; str.format("#%06X", col & 0xFFFFFF); item.SetAttr(attr, str); } } void TReport_mask::save_section(const TReport_section& rs, TXmlItem& item) const { char* tipo = NULL; switch (rs.type()) { case 'H': tipo = "Head"; break; case 'F': tipo = "Foot"; break; default : tipo = "Body"; break; } item.SetAttr("type", tipo); item.SetAttr("level", rs.level()); item.SetAttr("hidden_if_needed", rs.hidden_if_needed()); item.AddChild("groupby") << rs.grouped_by(); for (int i = 0; i < rs.items(); i++) { const TReport_field& rf = rs.field(i); TXmlItem& field = item.AddChild("field"); field.SetAttr("type", rf.type_name()); RCT rct; rf.get_rect(rct); set_num_attr(field, "x", rct.left); set_num_attr(field, "y", rct.top); set_num_attr(field, "width", rct.right - rct.left); set_num_attr(field, "height", rct.bottom - rct.top, 100); set_col_attr(field, "bg_color", rf.back_color(), COLOR_WHITE); set_col_attr(field, "fg_color", rf.fore_color(), COLOR_BLACK); switch (rf.horizontal_alignment()) { case 'C': field.SetAttr("align", "center"); break; case 'R': field.SetAttr("align", "right"); break; case 'J': field.SetAttr("align", "justify"); break; default : break; }; switch (rf.vertical_alignment()) { case 'T': field.SetAttr("valign", "top"); break; case 'C': field.SetAttr("valign", "center"); break; default : break; }; field.SetAttr("border", rf.border()); field.SetAttr("text", rf.picture()); if (rf.field().not_empty()) field.AddChild("source") << rf.field(); } } bool TReport_mask::save_report() { bool ok = _curr_report.not_empty(); if (!ok) ok = get_rep_path(_curr_report); if (!ok) return field(F_CODICE).on_key(K_ENTER); // Segnala errore char name[_MAX_FNAME]; xvt_fsys_parse_pathname (_curr_report, NULL, NULL, name, NULL, NULL); ok = *name > ' '; if (ok) { TXmlItem xml; xml.SetTag("report"); xml.SetAttr("Name", name); xml.AddChild("description") << get(F_DESCR); for (int i = 0; i < 4; i++) { const char* sectype = "HBF"; for (int j = 0; j < 3; j++) { TReport_section* rs = _report.find_section(sectype[j], i); if (rs != NULL && (rs->height() > 0 || rs->items() > 0)) { TXmlItem& sec = xml.AddChild("section"); save_section(*rs, sec); } } } xml.AddChild("sql") << get(F_SQL); xml.Save(_curr_report); } return ok; } bool TReport_mask::save_if_needed() { if (!_is_dirty) return true; if (!yesno_box(TR("Si desidera registrare il report?"))) return false; return save_report(); } void TReport_mask::global_reset() { _report.destroy(); reset(); update_report(); } bool TReport_mask::load_report() { TFilename path; get_rep_path(path); bool ok = path.exist(); if (ok) { _curr_report = path; global_reset(); ok = _report.load(path); if (ok) { path = path.name(); path.ext(""); set(F_CODICE, path); set(F_SQL, _report.sql(), true); set(F_DESCR, _report.description()); field(F_SQL).set_dirty(false); _is_dirty = false; TTree_field& sections = tfield(F_SECTIONS); _tree.goto_node('B', 1); sections.select_current(); update_report(); } } return ok; } bool TReport_mask::delete_report() { TFilename path; get_rep_path(path); const bool ok = yesno_box(FR("Si desidera eliminare il file %s"), (const char*)path); if (ok) { ::remove(path); global_reset(); } return ok; } void TReport_mask::on_print() { } TReport_section& TReport_mask::curr_section() { TTree_field& sections = tfield(F_SECTIONS); sections.goto_selected(); return _tree.curr_section(); } void TReport_mask::update_report() const { TTree_field& tf = tfield(F_SECTIONS); tf.win().force_update(); TReport_drawer& rd = (TReport_drawer&)field(F_REPORT); rd.win().force_update(); } void TReport_mask::add_field() { TReport_section& rs = curr_section(); TReport_field_mask m; m.set(F_DX, 10); m.set(F_DY, 1); m.disable(DLG_DELREC); if (m.run() == K_ENTER) { TReport_field* rf = new TReport_field; m.get_field(*rf); rs.add(rf); update_report(); } } void TReport_mask::edit_field(TReport_field& rf) { TReport_field_mask m; m.set_field(rf); const KEY key = m.run(); switch(key) { case K_ENTER: m.get_field(rf); break; case K_DEL: { TReport_section& rs = rf.section(); for (int i = rs.last(); i >= 0; i--) if (rs.objptr(i) == &rf) { rs.destroy(i, true); break; } } break; default: break; } update_report(); } void TReport_mask::fields_properties() { TReport_section& rs = curr_section(); TReport_sheet sheet(rs); int first, last; int selected = sheet.selection(first, last); if (selected == 1) { TReport_field& rf = rs.field(first); edit_field(rf); return; } KEY key = K_ENTER; while (key != K_ESC) { key = sheet.run(); selected = sheet.selection(first, last); if (selected == 0 && (key == K_ENTER || key == K_DEL)) { first = last = sheet.selected(); selected = 1; sheet.check(first); } switch (key) { case K_INS: add_field(); break; case K_ENTER: { for (int i = first; i <= last; i++) if (sheet.checked(i)) { TReport_field& rf = rs.field(i); edit_field(rf); } } break; case K_DEL: if (selected > 0 && yesno_box(FR("Comfermare la cancellazione di %d elementi"), selected)) { for (int i = last; i >= first; i--) if (sheet.checked(i)) rs.destroy(i, true); } break; default: break; } update_report(); } } void TReport_mask::section_properties() { TReport_section& rs = curr_section(); TReport_section_mask m; m.set_section(rs); switch (m.run()) { case K_ENTER: m.get_section(rs); _is_dirty = true; break; case K_DEL: rs.report().kill_section(rs.type(), rs.level()); _is_dirty = true; break; default: break; } if (_is_dirty) update_report(); } bool TReport_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_CODICE: if (e == fe_button) { if (select_report()) e = fe_modify; } if (e == fe_modify) { save_if_needed(); load_report(); } break; case F_SECTIONS: if (e == fe_init || e == fe_modify) { update_report(); const TReport_section& rs = _tree.curr_section(); const bool ok = strchr("HBF", rs.type()) != NULL; enable(-1, ok); } break; case F_TYPE: if (e == fe_button && o.active()) add_field(); break; case F_FLD_PROPERTIES: if (e == fe_button && o.active()) fields_properties(); break; case F_SEC_PROPERTIES: if (e == fe_button && o.active()) section_properties(); break; case F_SQL: if (e == fe_init || e == fe_modify) enable(F_SHOW_QRY, !o.empty()); break; case F_NEW_QRY: if (e == fe_button) { TExternal_app q("ba8 -1"); q.run(); } break; case F_IMPORT_QRY: if (e == fe_button) select_query(); break; case F_SHOW_QRY: if (e == fe_button) { TSQL_recordset qry(get(F_SQL)); if (qry.columns() > 0) { TRecordset_sheet sheet(qry); sheet.run(); } } break; case DLG_PRINT: if (e == fe_button) { on_print(); return false; } break; case DLG_NEWREC: if (e == fe_button) { save_if_needed(); global_reset(); } break; case DLG_FINDREC: if (e == fe_button) send_key(K_F9, F_CODICE); case DLG_SAVEREC: if (e == fe_button) { get_rep_path(_curr_report); save_report(); } break; case DLG_DELREC: if (e == fe_button && jolly == 0) // Elimina della Toolbar { delete_report(); return false; // Do not exit! } break; case DLG_QUIT: save_if_needed(); break; default: break; } return true; } TReport_mask::TReport_mask() : _tree(_report), _is_dirty(false) { read_mask("ba8300a", 0, -1); set_handlers(); TTree_field& albero = tfield(F_SECTIONS); RCT rct_sec; albero.get_rect(rct_sec); RCT rct_rep; field(F_REPORT).get_rect(rct_rep); rct_rep.left = rct_sec.right+ROWY; rct_rep.right -= ROWY; rct_rep.bottom -= ROWY; field(F_REPORT).set_rect(rct_rep); _tree.goto_node('B',1); const int ih = _tree.image_height(); if (ih > CHARY) albero.set_row_height(ih); albero.set_tree(&_tree); _tree.goto_root(); _tree.expand_all(); TReport_drawer& rd = (TReport_drawer&)field(F_REPORT); rd.set_report(&_report); } /////////////////////////////////////////////////////////// // TReporter_app /////////////////////////////////////////////////////////// class TReporter_app : public TSkeleton_application { protected: virtual void main_loop(); }; void TReporter_app::main_loop() { TReport_mask* msk = new TReport_mask; msk->run(); delete msk; } int ba8300(int argc, char* argv[]) { TReporter_app app; app.run(argc, argv, TR("Report Generator")); return 0; }