#include "ba8300.h" #include "ba8301.h" #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////// // TReport_tree /////////////////////////////////////////////////////////// void describe_section(char type, int level, TString& str) { if (level <= 0) { switch (type) { case 'H': str << TR("Testa"); break; case 'B': str << TR("Sfondo"); 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; } } else { switch (type) { case 'H': str << TR("Testa"); break; case 'B': str << TR("Corpo"); break; case 'F': str << TR("Coda"); break; default : break; } str << ' '; if (level < 10 && (type == 'H' || type == 'F')) { if (level <= 1) str << TR("Report"); else str << TR("Gruppo") << ' ' << (level-1); } else str << level; } } bool TReport_tree::get_description(TString& str) const { const char type = _curr[0]; const int level = atoi(_curr.mid(1)); describe_section(type, level, str); if (type != 'R' && type != 'P') str << " (" << _curr << ')'; 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; } int TReport_tree::curr_level() const { return atoi((const char*)_curr + 1); } TReport_section& TReport_tree::curr_section() const { char type = _curr[0]; int level = curr_level(); if (type == 'R' || type == 'P') { type = 'B'; level = type == 'R'; } return _report.section(type, level); } bool TReport_tree::goto_root() { return goto_node('P', 0); } bool TReport_tree::goto_firstson() { const char ntype = 'H'; int nlevel = -1; switch (_curr[0]) { case 'P': nlevel = 0; break; case 'R': nlevel = 1; break; case 'B': if (_curr[1] > '0') { const int first_son = curr_level() * 10 + 1; if (_report.find_section('B', first_son)) nlevel = first_son; } break; default: break; } return goto_node(ntype, nlevel); } bool TReport_tree::goto_rbrother() { const char type = _curr[0]; const int level = curr_level(); 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 { if (level > 10) // Subsections { switch (type) { case 'H': ntype = 'B'; nlevel = level; break; case 'B': ntype = 'F'; nlevel = level; break; case 'F': if (_report.find_section('B', level+1)) // Header del fratello { ntype = 'H'; nlevel = level+1; } break; default: break; } } else { switch (type) { case 'H': if (level < _report.find_max_level('H')) { ntype = 'H'; nlevel = level+1; } else { ntype = 'B'; nlevel = 1; } break; case 'B': if (level < _report.find_max_level('B')) { ntype = 'B'; nlevel = level+1; } else { ntype = 'F'; nlevel = _report.find_max_level('F'); } break; case 'F': if (level > 1) { ntype = 'F'; nlevel = level-1; } break; default: break; } } } return goto_node(ntype, nlevel); } bool TReport_tree::goto_node(const TString &id) { const int level = atoi((const char*)id + 1); return goto_node(id[0], level); } bool TReport_tree::has_son() const { bool yes = false; switch (_curr[0]) { case 'P': case 'R': yes = true; break; case 'B': { const int level = curr_level(); if (level > 0) yes = _report.find_section('B', level * 10 + 1) != NULL; } break; default: break; } return yes; } bool TReport_tree::has_rbrother() const { const TString8 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 _curr[0] != 'P' && _curr[0] != 'R'; } bool TReport_tree::goto_father() { bool yes = has_father(); if (yes) { const int level = curr_level(); if (level > 10) // Subsection { yes = goto_node('B', level/10); } else { const char ntype = _curr[1] == '0' ? 'P' : 'R'; yes = goto_node(ntype, 0); } } return yes; } bool TReport_tree::has_lbrother() const { const TString8 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_level(); 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; default : break; } nlevel = level; } else // Report { if (level > 10) // Subsection { switch (type) { case 'B': ntype = 'H'; nlevel = level; break; case 'F': ntype = 'B'; nlevel = level; break; case 'H': if (level % 10 > 1) { ntype = 'F'; nlevel = level-1; } default: break; } } else { switch (type) { case 'F': if (level < _report.find_max_level('F')) { ntype = 'F'; nlevel = level+1; } else { ntype = 'B'; nlevel = _report.find_max_level('B'); } break; case 'B': if (level > 1) { ntype = 'B'; nlevel = level-1; } else { ntype = 'H'; nlevel = 1; } break; case 'H': if (level > 1) { 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; // Testa aquila case 'B': id = 1811; break; // Corpo aquila case 'F': id = 1812; break; // Coda aquila default : break; } if (id > 0) { const int sub = _curr.len(); if (sub > 2) { if (sub > 3) id += 6; // Sub-Subsection (uovo) else id += 3; // Subsection (pulcino) } } else { id = selected ? 177 : 178; // Cartelle aperte/chiuse a caso } return id > 0 ? get_res_image(id) : TTree::image(selected); } int TReport_tree::image_height() const { const TImage* img = image(false); return img != NULL ? img->height() : 0; } /////////////////////////////////////////////////////////// // TPrinter_font_mask /////////////////////////////////////////////////////////// class TPrinter_font_mask : public TAutomask { XVT_FNTID _font; virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TPrinter_font_mask(XVT_FNTID font); }; bool TPrinter_font_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { PRINT_RCD* rcd = printer().get_printrcd(); if (rcd == NULL) return false; switch (o.dlg()) { case 101: if (e == fe_init) { o.set(printer().printername()); } break; case 102: if (e == fe_init) { const int MAX_FAMILIES = 256; char* family[MAX_FAMILIES]; const int num_families = (int)xvt_fmap_get_families(rcd, family, MAX_FAMILIES); TToken_string fn(num_families * 16); for (int i = 0; i < num_families; i++) { fn.add(family[i]); xvt_mem_free(family[i]); } TList_field& fonts = (TList_field&)o; fonts.replace_items(fn, fn); TString80 buf; xvt_font_get_family(_font, buf.get_buffer(), buf.size()); fonts.set(buf); } if (e == fe_init || e == fe_modify) { TList_field& lst = (TList_field&)field(103); TString4 old_size = lst.get(); if (old_size.empty()) old_size << xvt_font_get_size(_font); const int MAXSIZES = 8; long sizes[MAXSIZES]; BOOLEAN scalable = FALSE; TString80 str = o.get(); const int num_sizes = (int)xvt_fmap_get_family_sizes(rcd, str.get_buffer(), sizes, &scalable, MAXSIZES); TToken_string pn1; if (scalable) { for (int i = 4; i < 96; i++) pn1.add(i); } else { if (num_sizes > 0) { for (int i = 0; i < num_sizes; i++) pn1.add(sizes[i]); } else pn1.add(printer().get_char_size()); // semper better than nothing } lst.replace_items(pn1, pn1); lst.set(old_size); lst.enable(pn1.items() > 1); } break; default: break; } return true; } TPrinter_font_mask::TPrinter_font_mask(XVT_FNTID font) : TAutomask(TR("Selezione Font nativo"), 1, 68, 5), _font(font) { add_string(101, 0, PR("Stampante "), 1, 1, 256, "LG", 50); add_list(102, 0, PR("Nome "), 1, 2, 50, "", "", ""); add_list(103, 0, PR("Dimensioni "), 1, 3, 2, "", "", ""); add_button(DLG_OK, 0, "", -12, -1, 10, 2); add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2); set_handlers(); } /////////////////////////////////////////////////////////// // TReport_base_mask /////////////////////////////////////////////////////////// bool TReport_base_mask::draw_3d_rect(short id, COLOR rgb) const { const int pos = id2pos(id); const bool ok = pos >= 0; if (ok) { TMask_field& f = fld(pos); WINDOW pw = f.parent(); if (f.active() && pw == curr_win()) { RCT rctfld; f.get_rect(rctfld); const int x = rctfld.right / CHARX + 1; const int y = rctfld.top / ROWY + 1; RCT rct = resize_rect(x, y, -3, 1, W_PLAIN, pw); rct.top = rctfld.top; rct.bottom = rctfld.bottom; xi_draw_3d_rect((XinWindow)pw, (XI_RCT*)&rct, TRUE, 2, BTN_LIGHT_COLOR, rgb, BTN_DARK_COLOR); } } return ok; } bool TReport_base_mask::choose_printer_font(XVT_FNTID font) { TPrinter_font_mask m(font); const bool ok = m.run() == K_ENTER; if (ok) { xvt_font_set_family(font, m.get(102)); xvt_font_set_size(font, m.get_int(103)); } return ok; } void TReport_base_mask::update() { const TMask_field& fld = field(F_FONT_SELECT); WINDOW pw = fld.parent(); if (fld.active() && curr_win() == pw) { RCT rctfld; fld.get_rect(rctfld); const int x = rctfld.right / CHARX + 1; const int y = rctfld.top / ROWY + 1; RCT& rct = resize_rect(x, y, -3, 2, W_PLAIN, pw); rct.top = rctfld.top; rct.bottom = rctfld.bottom; xi_draw_3d_rect((XinWindow)pw, (XI_RCT*)&rct, TRUE, 2, MASK_LIGHT_COLOR, _bgcolor, MASK_DARK_COLOR); xvt_rect_deflate(&rct, 2, 2); xvt_dwin_set_clip(win(), &rct); XVT_FNTID fontid = xvt_font_create(); xvt_font_copy(fontid, _font.get_xvt_font(*this), XVT_FA_ALL); xvt_font_set_size(fontid, _font.size()); xvt_dwin_set_font(pw, fontid); set_opaque_text(false); set_color(_fgcolor, _bgcolor); advanced_draw_text_line(pw, _font.name(), rct, _halign, _valign); xvt_font_destroy(fontid); } const short cid[4] = { F_FGCOLOR, F_BGCOLOR, F_SHCOLOR, 0 }; const COLOR col[4] = { _fgcolor, _bgcolor, _shcolor, 0 }; for (int i = 0; i < 3; i++) draw_3d_rect(cid[i], col[i]); } bool TReport_base_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_FGCOLOR: if (e == fe_button) { _fgcolor = choose_color(_fgcolor, o.parent()); draw_3d_rect(F_FGCOLOR, _fgcolor); } break; case F_BGCOLOR: if (e == fe_button) { _bgcolor = choose_color(_bgcolor, o.parent()); draw_3d_rect(F_BGCOLOR, _bgcolor); } break; case F_SHCOLOR: if (e == fe_button) { _shcolor = choose_color(_shcolor, o.parent()); draw_3d_rect(F_SHCOLOR, _shcolor); } break; case F_PATTERN: if (e == fe_modify) force_update(); break; case F_FONT_SELECT: if (e == fe_button) { XVT_FNTID font = xvt_font_create(); xvt_font_copy(font, _font.get_xvt_font(*this), XVT_FA_ALL); xvt_font_set_size(font, _font.size()); if (xvt_dm_post_font_sel(win(), font, NULL, 0)) { TString80 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); _font.create(name, size, style); _font_changed = true; force_update(); } xvt_font_destroy(font); } break; case F_PRFONT_SELECT: if (e == fe_button) { XVT_FNTID font = xvt_font_create(); xvt_font_copy(font, _font.get_xvt_font(*this), XVT_FA_ALL); xvt_font_set_size(font, _font.size()); if (choose_printer_font(font)) { 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); _font.create(name, size, style); _font_changed = true; force_update(); } xvt_font_destroy(font); } break; case F_HALIGN: case F_VALIGN: if (e == fe_init || e == fe_modify) { _halign = get(F_HALIGN)[0]; _valign = get(F_VALIGN)[0]; force_update(); } break; case F_PRESCRIPT: case F_POSTSCRIPT: if (e == fe_close) { TReport_script s; s.set(o.get()); _report.set_interactive(true); s.compile(_report); _report.set_interactive(false); } break; default: break; } return true; } void TReport_base_mask::set_font_info(const TReport_font& font) { _font = font; } bool TReport_base_mask::get_font_info(TReport_font& font) const { const bool ok = _font_changed; if (ok) font = _font; return ok; } void TReport_base_mask::kill_special_pattern() { if (id2pos(F_PATTERN) > 0) { TList_field& p = lfield(F_PATTERN); TToken_string cod = p.get_codes(); if (cod.get_pos("10") > 0) { cod.cut(cod.rfind(cod.separator())); TToken_string val = p.get_values(); val.cut(val.rfind(val.separator())); p.replace_items(cod, val); } } } TReport_base_mask::TReport_base_mask(const char* name, TReport& rep) : TAutomask(name), _report(rep), _font_changed(false), _halign('C'), _valign('C'), _fgcolor(COLOR_BLACK), _bgcolor(COLOR_WHITE) { // Toglie le sfumature ai mortali if (!is_power_reseller(true)) kill_special_pattern(); } /////////////////////////////////////////////////////////// // TReport_field_mask /////////////////////////////////////////////////////////// void TReport_field_mask::set_num(short id, long num) { set(id, num2str(num)); } long TReport_field_mask::get_num(short id) const { return str2num(get(id)); } void TReport_field_mask::update() { draw_3d_rect(F_TXCOLOR, _txcolor); TReport_base_mask::update(); } void TReport_field_mask::vedo_non_vedo() { const char type = get(F_TYPE)[0]; const bool is_currency = type == 'P' || type == 'V'; const bool is_numeric = is_currency || type == 'N'; const bool is_text = is_numeric || strchr("ADST", type) != NULL; show(F_HIDE_ZEROES, is_numeric || type == 'D'), show(F_HALIGN, is_text || type == 'B'); enable(F_HALIGN, !is_numeric); if (is_numeric) set(F_HALIGN, "R"); // Forzo allineamento a destra dei numeri show(F_VALIGN, is_text || type == 'B'); show(F_TEXT, is_text && !is_currency); show(F_HIDE_DOTS, is_currency); show(F_DYNAMIC_HEIGHT, type == 'S'); show(F_FGCOLOR, type != 'I'); show(F_BGCOLOR, type != 'L'); show(F_TXCOLOR, is_text); show(F_PATTERN, type != 'L' && type != 'I' && type != 'B'); show(F_RADIUS, type != 'E' && type != 'L' && type != 'I' && type != 'B'); show(F_SHADE_OFFSET,type != 'E' && type != 'L' && type != 'B'); show(F_FONT_SELECT, is_text); // Bottone font show(F_PRFONT_SELECT, is_text); // Bottone font stampante enable(DLG_BAR, is_text); // Bottone font sulla toolbar show(F_SOURCE, (is_text || type == 'I' || type == 'B') && type != 'T'); show(F_SOURCE2, field(F_SOURCE).shown()); enable(DLG_FINDREC, is_text && type != 'T'); show(F_CODVAL, is_currency); // Codice valuta di riferimento show(F_LINK, strchr("DNS", type) != NULL); // Chi puo' essere un link? show(F_PRESCRIPT, is_text); show(F_POSTSCRIPT, is_text); enable_page(3, type == 'A'); if (is_running()) force_update(); } bool TReport_field_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch(o.dlg()) { case F_TXCOLOR: if (e == fe_button) { _txcolor = choose_color(_txcolor, o.parent()); force_update(); } break; case F_TYPE: if (e == fe_init || e == fe_modify) { vedo_non_vedo(); if (e == fe_modify) { if (strchr("ELR", o.get()[0]) != NULL && get_int(F_BORDER) == 0) set(F_BORDER, 2); // Propongo un bordo visibile per le linee } } break; case F_X: case F_Y: case F_DX: case F_DY: case F_RADIUS: case F_SHADE_OFFSET: if (e == fe_modify) { const int num = get_num(o.dlg()); set_num(o.dlg(), num); // Reformat } break; case F_LIST: if (e == fe_close) { TSheet_field& sheet = sfield(F_LIST); TAssoc_array ass; FOR_EACH_SHEET_ROW(sheet, i, row) { if (ass.add(row->get(0))) return error_box(TR("E' necessario specificare codici diversi")); } if (ass.items() < 2) return error_box(TR("Specificare almeno due codici")); } break; case DLG_FINDREC: if (e == fe_button) { TRecordset* rex = _rf.section().recordset(); if (rex == NULL) rex = _report.recordset(); if (rex != NULL && rex->columns() > 0) { TArray_sheet sheet(-1, -1, -1, 20, TR("Colonne Query"), HR("Nome@16|Tipo@8|Dimensoni@R")); TToken_string row; for (size_t i = 0; i < rex->columns(); i++) { const TRecordset_column_info& info = rex->column_info(i); row = info._name; switch (info._type) { case _alfafld: row.add("Stringa"); break; case _boolfld: row.add("Logico"); break; case _datefld: row.add("Data"); break; case _memofld: row.add("Memo"); break; default : row.add("Numero"); break; } row.add(info._width); sheet.add(row); } if (sheet.run() == K_ENTER) { row = sheet.row(-1); set(F_SOURCE, row.get(0)); char tipo = row.get_char(1); int width = row.get_int(2); switch (tipo) { case 'D':width = 10; break; case 'L':tipo = 'S'; break; case 'M':tipo = 'S'; width = 50; break; default: break; } const char str[2] = { tipo, '\0' }; set(F_TYPE, str); set(F_DX, width); } } else warning_box("Query non definita"); } break; default: break; } return TReport_base_mask::on_field_event(o, e, jolly); } void TReport_field_mask::set_field(const TReport_field& rf) { char str[2] = { rf.type(), '\0' }; set(F_TYPE, str, true); if (strchr("ELR", rf.type())) kill_special_pattern(); const TReport_rct& r = rf.get_rect(); set(F_ID, rf.id()); set_num(F_X, r.left()); set_num(F_Y, r.top()); set_num(F_DX, r.width()); set_num(F_DY, r.height()); set(F_HIDDEN, rf.hidden() ? "X" : ""); set(F_DISABLED, rf.deactivated() ? "X" : ""); set(F_HIDE_ZEROES, rf.zeroes_hidden() ? "X" : ""); set(F_HIDE_DOTS, rf.picture().find('.') < 0); set(F_DYNAMIC_HEIGHT, rf.dynamic_height() ? "X" : ""); set(F_GROUPS, rf.groups()); set(F_CODVAL, rf.codval()); set(F_LINK, rf.link()); str[0] = rf.horizontal_alignment(); set(F_HALIGN, str); str[0] = rf.vertical_alignment(); set(F_VALIGN, str); set(F_BORDER, rf.border()); set(F_PATTERN, rf.pattern()); set_num(F_RADIUS, rf.radius()); set_num(F_SHADE_OFFSET, rf.shadow_offset()); set(F_SHADE_ANGLE, rf.shade_angle()); _txcolor = rf.text_color(); _fgcolor = rf.fore_color(); _bgcolor = rf.back_color(); _shcolor = rf.shade_color(); set(F_TEXT, rf.picture()); set(F_SOURCE, rf.field()); set(F_SOURCE2, rf.alternate_field()); set_font_info(rf.font()); set(F_PRESCRIPT, rf.prescript()); set(F_POSTSCRIPT, rf.postscript()); if (rf.type() == 'A') { TSheet_field& list = sfield(F_LIST); rf.get_list(list.rows_array()); } } void TReport_field_mask::get_field(TReport_field& rf) const { rf.set_type(get(F_TYPE)[0]); rf.set_id(get_int(F_ID)); rf.set_pos(get_num(F_X), get_num(F_Y)); rf.set_size(get_num(F_DX), get_num(F_DY)); rf.show(!get_bool(F_HIDDEN)); rf.activate(!get_bool(F_DISABLED)); rf.hide_zeroes(field(F_HIDE_ZEROES).active() && get_bool(F_HIDE_ZEROES)); rf.set_dynamic_height(get_bool(F_DYNAMIC_HEIGHT)); rf.set_groups(get(F_GROUPS)); rf.set_codval(get(F_CODVAL)); rf.set_link(get(F_LINK)); rf.set_horizontal_alignment(get(F_HALIGN)[0]); rf.set_vertical_alignment(get(F_VALIGN)[0]); rf.set_pattern((PAT_STYLE)get_int(F_PATTERN)); rf.set_border(get_int(F_BORDER)); rf.set_radius(get_num(F_RADIUS)); rf.set_shadow_offset(get_num(F_SHADE_OFFSET)); rf.set_shade_angle(get_int(F_SHADE_ANGLE)); rf.set_text_color(_txcolor); rf.set_fore_color(_fgcolor); rf.set_back_color(_bgcolor); rf.set_shade_color(_shcolor); if (strchr("VP", rf.type()) != NULL) rf.set_picture(get_bool(F_HIDE_DOTS) ? "#########,@@" : "###.###.###,@@"); else rf.set_picture(get(F_TEXT)); rf.set_field(get(F_SOURCE)); rf.set_alternate_field(get(F_SOURCE2)); TReport_font f; if (get_font_info(f)) rf.set_font(f); rf.set_prescript(get(F_PRESCRIPT)); rf.set_postscript(get(F_POSTSCRIPT)); if (rf.type() == 'A') { const TSheet_field& list = sfield(F_LIST); rf.set_list(list.rows_array()); } } TReport_field_mask::TReport_field_mask(TReport_field& rf) : TReport_base_mask("ba8300b", rf.section().report()), _rf(rf) { set_field(rf); } /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// static TString16 _str; const TString& num2str(int num) { 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; } short str2num(const TString& str) { _str = str; _str.replace(',', '.'); real n(_str); n *= CENTO; return (short)n.integer(); } /////////////////////////////////////////////////////////// // TReport_window /////////////////////////////////////////////////////////// class TReport_window : public TField_window { TReport* _report; char _type; int _level; PNT _dpi; bool _draw_bg; int _dragging; TReport_pnt _pt_drag_start; PNT _pt_click, _pt_drag_offset; RCT _rct_drag; TReport_image_cache _images; static TArray _clipboard; private: virtual TPoint dev2log(const PNT& pt) const; virtual PNT log2dev(long x, long y) const; protected: virtual long handler(WINDOW win, EVENT* ep); virtual void update(); virtual bool on_key(KEY k); protected: void draw_bg(); void draw_grid(); void snap(TReport_pnt& pnt, bool shift) const; void snap(TReport_rct& pnt, bool shift) const; void draw_dragster(); void draw_field(const TReport_field& rf); void draw_broken_paper(const TReport_field& rf); void popup_menu(); void popup_cut(); void popup_copy(); void popup_paste(); bool do_zoom(int k, bool reflect); int cpi() const; int lpi() const; bool advanced_set_draw_tools(PAT_STYLE pat, int border, COLOR fore, COLOR back); void advanced_draw_rect(const RCT& r, PAT_STYLE pat, int border, COLOR fore, COLOR back, COLOR shade, int radius, int shadow, int angle); void offset_selection(TReport_section& rs, const TReport_size& p); // low level offset public: PNT rep2dev(const TReport_pnt& pt) const; void rep2dev(const TReport_rct& rr, RCT& dr) const; void dev2rep(const RCT& dr, TReport_rct& rr) const; TReport_pnt dev2rep(const PNT& pt) const; TReport_section& curr_section() const { return _report->section(_type, _level); } void set_report_section(TReport_section& rs); int get_selection_rect(TReport_rct& rct) const; bool pick(const TReport_pnt& ptlog) const; void clear_selection(); bool select(const TReport_rct& rct, bool inter); void offset_selection(const TReport_size& p); // safe offset with <0 checking void resize_selection(const TReport_size& p); bool test_corner(const RCT& rct, const PNT& pt, PNT& opposite) const; TReport_field* first_selected() const; bool add_field(const TReport_rct& rct); TReport_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner); virtual ~TReport_window() { } }; TArray TReport_window::_clipboard; void TReport_window::set_report_section(TReport_section& rs) { _report = &rs.report(); _type = rs.type(); _level = rs.level(); TString str; describe_section(rs.type(), rs.level(), str); xvt_pane_set_title(win(), str); } bool TReport_window::pick(const TReport_pnt& ptlog) const { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM_BACK(rs, i, o) { TReport_field& f = *(TReport_field*)o; const TReport_rct& rct = f.get_rect(); if (rct.contains(ptlog)) { 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); } } int TReport_window::get_selection_rect(TReport_rct& rct) const { TReport_section& rs = curr_section(); int full = 0; FOR_EACH_ARRAY_ITEM(rs, i, o) { const TReport_field& f = *(const TReport_field*)o; if (f.selected()) { const TReport_rct& fr = f.get_rect(); if (!full) rct = fr; else rct.merge(fr); full++; } } return full; } void TReport_window::offset_selection(TReport_section& rs, const TReport_size& p) { FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; if (f.selected()) f.offset(p); } } void TReport_window::offset_selection(const TReport_size& p) { TReport_section& rs = curr_section(); offset_selection(rs, p); // Se sposto fuori dal foglio riporto dentro la selezione TReport_rct selrct; get_selection_rect(selrct); if (selrct.x < 0 || selrct.y < 0) { const TReport_size off(selrct.x < 0 ? -selrct.x : 0, selrct.y < 0 ? -selrct.y : 0); offset_selection(rs, off); } rs.sort(); } void TReport_window::resize_selection(const TReport_size& p) { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; if (f.selected()) { TReport_size s = f.get_rect().size(); s += p; if (s.x > 0 && s.y > 0) f.set_size(s.x, s.y); } } } TReport_field* TReport_window::first_selected() const { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; if (f.selected()) return &f; } return NULL; } bool TReport_window::select(const TReport_rct& rct, bool inter) { bool some = false; clear_selection(); TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; const TReport_rct& r = f.get_rect(); const bool yes = inter ? rct.intersects(r) : rct.contains(r); if (yes) { some = true; f.select(); } } return some; } void TReport_window::draw_dragster() { set_mode(M_NOT_XOR); set_pen(COLOR_BLACK); xvt_dwin_draw_dotted_rect(win(), &_rct_drag); set_mode(M_COPY); } void TReport_window::snap(TReport_pnt& pnt, bool shift) const { const int kx = shift ? 10 : 100; const int ky = shift ? 10 : 50; pnt.x = ((pnt.x+kx/2) / kx) * kx; pnt.y = ((pnt.y+ky/2) / ky) * ky; } void TReport_window::snap(TReport_rct& rct, bool shift) const { TReport_pnt p0 = rct; snap(p0, shift); TReport_pnt p1(rct.right(), rct.bottom()); snap(p1, shift); rct.set(p0, p1-p0); } bool TReport_window::on_key(KEY k) { switch (k) { case 'G': dispatch_e_menu(win(), POPUP_UNGROUP); return true; case 'g': dispatch_e_menu(win(), POPUP_GROUP); return true; case K_LEFT: offset_selection(TReport_size(-50, 0)); force_update(); return true; case K_LEFT+K_SHIFT: resize_selection(TReport_size(-50, 0)); force_update(); return true; case K_RIGHT: offset_selection(TReport_size(+50, 0)); force_update(); return true; case K_RIGHT+K_SHIFT: resize_selection(TReport_size(+50, 0)); force_update(); return true; case K_DOWN: offset_selection(TReport_size(0, +25)); force_update(); return true; case K_DOWN+K_SHIFT: resize_selection(TReport_size(0, +25)); force_update(); return true; case K_UP: offset_selection(TReport_size(0, -25)); force_update(); return true; case K_UP+K_SHIFT: resize_selection(TReport_size(0, -25)); force_update(); return true; case K_DEL: dispatch_e_menu(win(), POPUP_CUT); return true; case '+': dispatch_e_menu(win(), POPUP_ZOOMIN); return true; case '-': dispatch_e_menu(win(), POPUP_ZOOMOUT); return true; case K_ENTER: dispatch_e_menu(win(), POPUP_PROPERTIES); return true; 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: if (k > K_CTRL) // Gestione acceleratori dispatch_e_char(parent(), k); break; } return TField_window::on_key(k); } void TReport_window::popup_menu() { MENU_ITEM menu[32]; // Stiamo larghi memset(menu, 0, sizeof(menu)); TReport_rct rct; const bool ful = curr_section().items() > 0; const bool sel = ful && get_selection_rect(rct) != 0; const bool clp = _clipboard.items() > 0; const bool sbg = curr_section().level() > 0 || curr_section().type() != 'B'; menu[ 0].tag = POPUP_CUT; menu[ 0].text = (char*)TR("Taglia"); menu[0].enabled = sel; menu[ 1].tag = POPUP_COPY; menu[ 1].text = (char*)TR("Copia"); menu[1].enabled = sel; menu[ 2].tag = POPUP_PASTE; menu[ 2].text = (char*)TR("Incolla"); menu[2].enabled = clp; menu[ 3].tag = POPUP_DUP; menu[ 3].text = (char*)TR("Duplica"); menu[3].enabled = sel; menu[ 4].tag = POPUP_CLEAR; menu[ 4].text = (char*)TR("Cancella"); menu[4].enabled = sel; menu[ 5].tag = POPUP_GROUP; menu[ 5].text = (char*)TR("Raggruppa");menu[5].enabled = sel; menu[ 6].tag = POPUP_UNGROUP; menu[ 6].text = (char*)TR("Dividi"); menu[6].enabled = sel; menu[ 7].tag = -1; menu[ 7].separator = true; menu[ 8].tag = POPUP_ZOOMIN; menu[ 8].text = (char*)TR("Zoom +"); menu[8].enabled = _dpi.v < 300; menu[ 9].tag = POPUP_ZOOMOUT; menu[ 9].text = (char*)TR("Zoom -"); menu[9].enabled = _dpi.v > 48; menu[10].tag = POPUP_BACKGROUND; menu[10].text = (char*)TR("Mostra sfondo"); menu[10].enabled = menu[10].checkable = sbg; menu[10].checked = sbg && _draw_bg; menu[11].tag = -1; menu[11].separator = true; menu[12].tag = POPUP_SELALL; menu[12].text = (char*)TR("Seleziona tutto"); menu[12].enabled = ful; menu[13].tag = POPUP_UNSELALL; menu[13].text = (char*)TR("Deseleziona tutto"); menu[13].enabled = ful; menu[14].tag = -1; menu[14].separator = true; menu[15].tag = POPUP_PROPERTIES; menu[15].text = (char*)TR("Proprieta'"); menu[15].enabled = true; menu[16].tag = POPUP_NEWFIELD; menu[16].text = (char*)TR("Nuovo"); menu[16].enabled = true; _pt_drag_start = dev2rep(_pt_click); xvt_menu_popup(menu, win(), _pt_click, 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()) { TReport_field* obj = (TReport_field*)rs.remove(i, true); obj->set_section(NULL); _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()) { TReport_field* cp = new TReport_field(f); cp->set_section(NULL); _clipboard.add(cp); } } } void TReport_window::popup_paste() { if (_clipboard.items() > 0) { const TReport_rct& rct = ((const TReport_field&)_clipboard[0]).get_rect(); TReport_pnt diff(_pt_drag_start.x-rct.left(), _pt_drag_start.y-rct.top()); snap(diff, false); if (diff.x != 0 || diff.y != 0) { clear_selection(); TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(_clipboard, i, o) { const TReport_field& oldf = *(TReport_field*)o; TReport_field* newf = new TReport_field(oldf); newf->select(); rs.add(newf); } offset_selection(TReport_size(diff.x, diff.y)); force_update(); } } } bool TReport_window::test_corner(const RCT& rct, const PNT& pt, PNT& opposite) const { int test = 0; if (pt.h >= rct.left && pt.h < rct.left+4) { opposite.h = rct.right; test = 1; } else if (pt.h > rct.right-4 && pt.h <= rct.right) { opposite.h = rct.left; test = 1; } if (test == 1) { if (pt.v >= rct.top && pt.v < rct.top+4) { opposite.v = rct.bottom; test = 2; } else if (pt.v <= rct.bottom && pt.v > rct.bottom-4) { opposite.v = rct.top; test = 2; } } return test == 2; } bool TReport_window::do_zoom(int k, bool reflect) { const int n = _dpi.v+k; const bool ok = n >= 48 && n < 300; if (ok) { _dpi.h = _dpi.v = n; curr_section().unmap_font(); force_update(); if (reflect) { const short buddy = owner().dlg() == F_REPORT ? F_REPORTH : F_REPORT; TWindowed_field& fld = (TWindowed_field&)owner().mask().field(buddy); TReport_window& win = (TReport_window&)fld.win(); win.do_zoom(k, false); } } return ok; } bool TReport_window::add_field(const TReport_rct& rct) { TReport_section& rs = curr_section(); TReport_field* rf = new TReport_field(&rs); rf->set_type('S'); rf->set_pos(((rct.left()+50)/100)*100, ((rct.top()+50)/100)*100); int w = ((rct.width()+50)/100)*100; if (w < 100) w = 100; int h = ((rct.height()+50)/100)*100; if (h < 100) h = 100; rf->set_size(w, h); TReport_field_mask m(*rf); m.disable(DLG_DELREC); const bool ok = m.run() == K_ENTER; if (ok) { m.get_field(*rf); rs.add(rf); force_update(); } else delete rf; return ok; } long TReport_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_MOUSE_DOWN: _pt_click = ep->v.mouse.where; switch (ep->v.mouse.button) { case 0: { const TReport_pnt pt = dev2rep(_pt_click); TReport_rct rct; int full = get_selection_rect(rct); if (!full || !rct.contains(pt)) { if (full && !ep->v.mouse.control) clear_selection(); pick(pt); full = get_selection_rect(rct); } if (full > 0) { rep2dev(rct, _rct_drag); if (full == 1 && test_corner(_rct_drag, ep->v.mouse.where, _pt_drag_offset)) { _dragging = 3; // Trascinamento rettangolo elastico XinCursor hand = xi_get_pref(XI_PREF_SIZE_CURSOR_RID); xvt_win_set_cursor(win, (CURSOR)hand); } else { _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; // Trascinamento rettangolo fisso 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); _pt_drag_offset.h = _pt_drag_offset.v = 0; _dragging = 1; // Trascinamento rettangolo di selezione } _pt_drag_start.x = rct.left(); _pt_drag_start.y = rct.top(); draw_dragster(); xvt_win_trap_pointer(win); } break; case 1: popup_menu(); break; default: break; } owner().mask().notify_focus_field(owner().dlg()); return 0L; // Termina qui la gestione del bottone case E_MOUSE_MOVE: { TMask& m = owner().mask(); const TReport_pnt p = dev2rep(ep->v.mouse.where); TString16 str; str.format("r:%5.1lf c:%5.1lf", p.y/100.0, p.x/100.0); statbar_set_title(TASK_WIN, str); 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; xvt_rect_set_pos(&_rct_drag, pt); break; case 3: xvt_rect_set(&_rct_drag, _pt_drag_offset.h, _pt_drag_offset.v, pt.h, pt.v); break; default: break; } draw_dragster(); } } break; case E_MOUSE_UP: if (_dragging != 0) { draw_dragster(); PNT pt = ep->v.mouse.where; if (abs(pt.h-_pt_click.h) > 2 || abs(pt.v-_pt_click.v) > 2) // Mi sono veramente spostato? { switch (_dragging) { case 1: { _rct_drag.right = pt.h; _rct_drag.bottom = pt.v; TReport_rct rct; dev2rep(_rct_drag, rct); const bool something = select(rct, pt.h < _rct_drag.left); if (!something && ep->v.mouse.control) add_field(rct); } break; case 2: { pt.h -= _pt_drag_offset.h; pt.v -= _pt_drag_offset.v; TReport_pnt offset = dev2rep(pt); snap(offset, ep->v.mouse.shift != 0); offset.x -= _pt_drag_start.x; offset.y -= _pt_drag_start.y; offset_selection(TReport_size(offset.x, offset.y)); } break; case 3: { TReport_field* rf = first_selected(); TReport_rct rct; dev2rep(_rct_drag, rct); snap(rct, ep->v.mouse.shift != 0); rf->set_pos(rct.x, rct.y); rf->set_size(rct.width(), rct.height()); } break; default: break; } } force_update(); _dragging = 0; xvt_win_release_pointer(); xvt_win_set_cursor(win, CURSOR_ARROW); } break; case E_MOUSE_DBL: _pt_drag_start = dev2rep(ep->v.mouse.where); dispatch_e_menu(win, POPUP_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_ZOOMIN: do_zoom(+24, true); break; case POPUP_ZOOMOUT: do_zoom(-24, true); break; case POPUP_BACKGROUND: _draw_bg = !_draw_bg; force_update(); break; case POPUP_SELALL: { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; f.select(); } force_update(); } break; case POPUP_UNSELALL: { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; f.select(false); } force_update(); } break; case POPUP_PROPERTIES: { clear_selection(); const bool full = pick(_pt_drag_start); dispatch_e_menu(parent(), full ? POPUP_PROPERTIES : POPUP_SECTION); } break; case POPUP_NEWFIELD: dispatch_e_menu(parent(), POPUP_NEWFIELD); break; case POPUP_GROUP: case POPUP_UNGROUP: { TToken_string gruppi(16, ' '); xvt_dm_post_string_prompt(TR("Codice gruppo"), gruppi.get_buffer(), gruppi.size()); gruppi.strip_double_spaces(); gruppi.trim(); if (gruppi.full()) { if (isdigit(gruppi[0])) { TReport_section& rs = curr_section(); FOR_EACH_ARRAY_ITEM(rs, i, o) { TReport_field& f = *(TReport_field*)o; if (f.selected()) { if (ep->v.cmd.tag == POPUP_GROUP) f.add_groups(gruppi); else f.del_groups(gruppi); } } } else error_box(TR("Codice gruppo non numerico")); } } break; default: break; } break; case E_HSCROLL: { // Riflette l'evento E_HSCROLL sull'altra finestra di anteprima spacciandolo per E_USER const short buddy = owner().dlg() == F_REPORT ? F_REPORTH : F_REPORT; TWindowed_field& fld = (TWindowed_field&)owner().mask().field(buddy); ep->type = E_USER; dispatch_event(fld.win().win(), *ep, false); ep->type = E_HSCROLL; } break; case E_USER: // Mi e' arrivato un E_HSCROLL camuffato E_USER dall'altra finestra di anteprima ep->type = E_HSCROLL; break; default: break; } return TField_window::handler(win, ep); } PNT TReport_window::log2dev(long rx, long ry) const { const int x = rx - origin().x * 100L; const int y = ry - origin().y * 100L; 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; } PNT TReport_window::rep2dev(const TReport_pnt& pt) const { return log2dev(pt.x, pt.y); } TReport_pnt TReport_window::dev2rep(const PNT& pt) const { const TPoint p = dev2log(pt); return TReport_pnt(p.x, p.y); } void TReport_window::dev2rep(const RCT& dr, TReport_rct& rr) const { const PNT dp0 = { dr.top, dr.left }; const PNT dp1 = { dr.bottom, dr.right }; const TReport_pnt p0 = dev2rep(dp0); const TReport_pnt p1 = dev2rep(dp1); rr.set(p0, p1-p0); } void TReport_window::rep2dev(const TReport_rct& rr, RCT& dr) const { const PNT dp0 = rep2dev(rr); const PNT dp1 = rep2dev(TReport_pnt(rr.right(), rr.bottom())); xvt_rect_set(&dr, dp0.h, dp0.v, dp1.h, dp1.v); } bool TReport_window::advanced_set_draw_tools(PAT_STYLE pat, int border, COLOR fore, COLOR back) { const bool has_pen = border > 0 && fore != COLOR_INVALID; const bool has_brush = pat > PAT_HOLLOW && back != COLOR_INVALID; const bool visible = has_pen || has_brush; if (visible) { if (has_pen) { const int pollici720 = border <= 1 ? 5 : (border-1)*10; // Spessore in 1/720 di pollice const double thickness = pollici720 * _dpi.h / 720.0; // Spessore in pixel if (thickness < 1.0) fore = blend_colors(fore, COLOR_WHITE, thickness); set_pen(fore, int(thickness+0.5), PAT_SOLID); } else hide_pen(); if (has_brush) set_brush(back, pat); else hide_brush(); } return visible; } void TReport_window::advanced_draw_rect(const RCT& r, PAT_STYLE pat, int border, COLOR fore, COLOR back, COLOR shade, int radius, int shadow, int angle) { WINDOW w = win(); if (shadow != 0 && (pat == PAT_SOLID || pat == PAT_SPECIAL)) // Disegna eventuale ombra { if (advanced_set_draw_tools(pat, 0, COLOR_GRAY, COLOR_GRAY)) { RCT rct = r; xvt_rect_offset(&rct, shadow, shadow); if (radius > 0) xvt_dwin_draw_roundrect(w, &rct, radius, radius); else xvt_dwin_draw_rect(w, &rct); } } if (pat == PAT_SPECIAL && shade != COLOR_INVALID) { xvt_dwin_draw_gradient_linear(w, &r, back, shade, angle); if (advanced_set_draw_tools(PAT_HOLLOW, border, fore, COLOR_INVALID)) // ha un bordo xvt_dwin_draw_rect(w, (RCT*)&r); } else { if (advanced_set_draw_tools(pat, border, fore, back)) { if (radius > 0) xvt_dwin_draw_roundrect(w, &r, radius, radius); else xvt_dwin_draw_rect(w, (RCT*)&r); } } } void TReport_window::draw_grid() { const int k = 100; const TReport_section& rs = curr_section(); int x = rs.width(); int y = rs.height(); if (x <= 0) x = 196*k; if (y <= 0) // Sezione ad altezza variabile { for (int i = 0; i < rs.items(); i++) { const TReport_field& rf = rs.field(i); const TReport_rct& rct = rf.get_rect(); const int fy = rct.bottom(); if (fy > y) y = fy; } const int mod = y % k; if (mod != 0) y += k-mod; } if (rs.type() == 'B' && rs.level() == 0) x = y = 196*k; // Disegna l'eventuale sfondo di sezione const bool draw_back = y > 0 && (rs.border() > 0 || rs.pattern() == PAT_SPECIAL || (rs.pattern() >= PAT_SOLID && rs.back_color() != COLOR_WHITE)); if (draw_back) { const PNT p = rep2dev(TReport_pnt(x, y)); RCT rct; xvt_rect_set(&rct, 0, 0, p.h, p.v); const PNT p0 = rep2dev(TReport_pnt(0, 0)); const PNT pr = rep2dev(TReport_pnt(rs.radius(), rs.radius())); const int radius = min(pr.h-p0.h, pr.v-p0.v); advanced_draw_rect(rct, rs.pattern(), rs.border(), rs.fore_color(), rs.back_color(), rs.shade_color(), radius, 0, rs.shade_angle()); } for (int i = x/k; i > 0; i--) { set_pen(i%10 ? XVT_MAKE_COLOR(232,232,255) : XVT_MAKE_COLOR(255,192,255)); line(0, i*k, x, i*k); line(i*k, 0, i*k, y <= 0 ? x : y); } if (y > 0) // Disegna barra di fine sezione { const PNT p = rep2dev(TReport_pnt(x, y)); RCT rct; xvt_vobj_get_client_rect(win(), &rct); if (p.v < rct.bottom) { hide_pen(); set_brush(MASK_BACK_COLOR, PAT_DIAGCROSS); rct.top = p.v; xvt_dwin_draw_rect(win(), &rct); } } } void TReport_window::draw_broken_paper(const TReport_field& rf) { set_pen(COLOR_LTGRAY); const TReport_rct& dr = rf.get_rect(); const int b = dr.bottom()-100; line(short(dr.x), short(b), short(dr.x), short(dr.y)); line(short(dr.x), short(dr.y), short(dr.right()), short(dr.y)); line(short(dr.right()), short(dr.y), short(dr.right()), short(b)); for (int x = dr.left(); x < dr.right(); ) { const int deltay = rand()%100; int deltax = 200; int ex = x + deltax; if (ex > dr.right()) { ex = dr.right(); deltax = ex-x; } line(short(x), short(b), short(x+deltax/2), short(b+deltay)); line(short(x+deltax/2), short(b+deltay), short(x+deltax), short(b)); x = ex; } } void TReport_window::draw_field(const TReport_field& rf) { const TReport_rct& rf_rect = rf.get_rect(); RCT r; rep2dev(rf_rect, r); int rad = 0; if (rf.radius() > 0) { const int width = r.right - r.left; rad = rf.radius() * width / rf.get_rect().width(); } int off = 0; if (rf.shadow_offset() > 0) { const int width = r.right - r.left; off = rf.shadow_offset() * width / rf.get_rect().width(); } PAT_STYLE back_pattern = PAT_HOLLOW; const int k = (rf.hidden() ? 1 : 0) + (rf.deactivated() ? 2 : 0); switch (k) { case 1: back_pattern = PAT_FDIAG; break; case 2: back_pattern = PAT_BDIAG; break; case 3: back_pattern = PAT_DIAGCROSS; break; default: back_pattern = PAT_HOLLOW; break; } switch (rf.type()) { case 'E': if (advanced_set_draw_tools(rf.pattern(), rf.border(), rf.fore_color(), rf.back_color())) xvt_dwin_draw_oval(win(), &r); back_pattern = PAT_HOLLOW; break; case 'I': { TVariant var; curr_section().report().evaluate(rf.field(), var, _alfafld); const TString& name = var.as_string(); const TImage* img = _images.image(name); if (img != NULL && img->ok()) img->draw(win(), r); advanced_draw_rect(r, PAT_HOLLOW, rf.border(), rf.fore_color(), COLOR_INVALID, COLOR_INVALID, 0, off, 0); } break; case 'L': if (advanced_set_draw_tools(PAT_SOLID, rf.border(), rf.fore_color(), COLOR_INVALID)) { const PNT f = { r.top, r.left }; xvt_dwin_draw_set_pos(win(), f); const PNT t = { r.bottom, r.right }; xvt_dwin_draw_line(win(), t); } back_pattern = PAT_HOLLOW; break; case 'R': advanced_draw_rect(r, rf.pattern(), rf.border(), rf.fore_color(), rf.back_color(), rf.shade_color(), rad, off, rf.shade_angle()); break; case 'T': { advanced_draw_rect(r, rf.pattern(), rf.border(), rf.fore_color(), rf.back_color(), rf.shade_color(), rad, off, rf.shade_angle()); const TString& str = rf.picture(); if (str.full()) { bool printed = false; xvt_dwin_set_font(win(), rf.font().get_xvt_font(*this)); set_color(rf.text_color(), rf.back_color()); if (rf_rect.height() > 100 && rf_rect.width() > 100) { TParagraph_string para(str, rf_rect.width()/100); if (para.items() > 1) { TString_array text; FOR_EACH_TOKEN(para, line) text.add(line); const int d10rh = (r.bottom-r.top)*1000/rf_rect.height(); // Altezza standard di 10 righe di testo advanced_draw_paragraph(win(), text, r, rf.horizontal_alignment(), rf.vertical_alignment(), d10rh); printed = true; } } if (!printed) advanced_draw_text_line(win(), str, r, rf.horizontal_alignment(), rf.vertical_alignment()); } } break; default : if (rf.dynamic_height()) draw_broken_paper(rf); else { advanced_draw_rect(r, rf.pattern(), rf.border(), rf.fore_color(), rf.back_color(), rf.shade_color(), rad, off, rf.shade_angle()); if (rf.border() <= 0) // Rendi comunque visibile il bordo dei campi che non ce l'hanno advanced_draw_rect(r, PAT_HOLLOW, 1, COLOR_LTGRAY, COLOR_INVALID, COLOR_INVALID, 0, 0, 0); } if (rf.link().not_empty()) { XVT_FNTID lnkfont = xvt_font_create(); xvt_font_copy(lnkfont, rf.font().get_xvt_font(*this), XVT_FA_ALL); xvt_font_set_style(lnkfont, XVT_FS_UNDERLINE); xvt_dwin_set_font(win(), lnkfont); xvt_font_destroy(lnkfont); set_color(rf.link_color(), rf.back_color()); } else { xvt_dwin_set_font(win(), rf.font().get_xvt_font(*this)); set_color(rf.text_color(), rf.back_color()); } TString str; if (rf.id() > 0) str << rf.id(); else str = rf.field(); advanced_draw_text_line(win(), str, r, rf.horizontal_alignment(), rf.vertical_alignment()); break; } if (back_pattern != PAT_HOLLOW) { set_pen(COLOR_LTGRAY); set_brush(COLOR_LTGRAY, back_pattern); xvt_dwin_draw_rect(win(), &r); } if (rf.selected()) { advanced_set_draw_tools(PAT_SOLID, 0, COLOR_WHITE, COLOR_GRAY); const int k = 5; RCT s = r; s.right = s.left+k; s.bottom = s.top+k; xvt_dwin_draw_rect(win(), &s); s = r; s.left = s.right-k; s.bottom = s.top+k; xvt_dwin_draw_rect(win(), &s); s = r; s.right = s.left+k; s.top = s.bottom-k; xvt_dwin_draw_rect(win(), &s); s = r; s.left = s.right-k; s.top = s.bottom-k; xvt_dwin_draw_rect(win(), &s); } } void TReport_window::draw_bg() { const TReport_section& rs = curr_section(); if (_draw_bg && (rs.level() > 0 || rs.type() != 'B')) { const TReport_section* back = _report->find_section('B', 0); if (back != NULL && back->items() > 0) { int offset_y = 0; if (rs.type() == 'F') { offset_y = back->height() - rs.height(); } else { const int lev = rs.type() == 'B' ? _report->find_max_level('H') : rs.level()-1; for (int i = lev; i > 0; i--) { const TReport_section* h = _report->find_section('H', i); if (h != NULL) offset_y += h->compute_size().y/100; } } update_thumb(origin().x, origin().y + offset_y); for (int i = 0; i < back->items(); i++) { const TReport_field& rf = back->field(i); draw_field(rf); } update_thumb(origin().x, origin().y - offset_y); } } } void TReport_window::update() { clear(COLOR_WHITE); // Cancella pagina draw_bg(); // Disegna sfondo draw_grid(); // Disegna griglia const TReport_section& rs = curr_section(); for (int i = 0; i < rs.items(); i++) { const TReport_field& rf = rs.field(i); draw_field(rf); // Disegna campo } } int TReport_window::cpi() const { return _report != NULL ? _report->cpi() : 12; } int TReport_window::lpi() const { return _report != NULL ? _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), _type('B'), _level(1), _draw_bg(false) { _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_section(TReport_section& rs) { TReport_window* w = (TReport_window*)_win; w->set_report_section(rs); } TReport_section& TReport_drawer::curr_section() { TReport_window* w = (TReport_window*)_win; return w->curr_section(); }