campo-sirio/ba/ba8301.cpp
guy 065f2502a3 Patch level : 10.0
Files correlati     : ba8.exe
Ricompilazione Demo : [ ]
Commento            :
 0001643: Gestione campi trasparenti nei report
Per quei campi dove non risulta settato il valore dello sfondo (trasparente, pieno, ecc..) metteremo di default pieno. Questo dovrebbe simulare il comportamento del programma prima della modifica.


git-svn-id: svn://10.65.10.50/trunk@20499 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-05-26 08:58:13 +00:00

2133 lines
55 KiB
C++
Executable File

#include "ba8300.h"
#include "ba8301.h"
#include <colors.h>
#include <defmask.h>
#include <diction.h>
#include <printer.h>
#include <reprint.h>
#include <utility.h>
#include <xinclude.h>
#include <statbar.h>
///////////////////////////////////////////////////////////
// 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);
if (f.active() && f.parent() == 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, f.parent());
rct.top = rctfld.top; rct.bottom = rctfld.bottom;
xi_draw_3d_rect((XinWindow)f.parent(), (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);
if (fld.active() && curr_win() == fld.parent())
{
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, fld.parent());
rct.top = rctfld.top; rct.bottom = rctfld.bottom;
xi_draw_3d_rect((XinWindow)fld.parent(), (XI_RCT*)&rct, TRUE, 2, MASK_LIGHT_COLOR,
_bgcolor, MASK_DARK_COLOR);
rct.left += 2; rct.right -= 2;
rct.top += 2; rct.bottom -= 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(fld.parent(), fontid);
set_color(_fgcolor, _bgcolor);
advanced_draw_text_line(fld.parent(), _font.name(), rct, _halign, _valign);
xvt_font_destroy(fontid);
}
const short cid[3] = { F_FGCOLOR, F_BGCOLOR, F_SHCOLOR };
const COLOR col[3] = { _fgcolor, _bgcolor, _shcolor };
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();
}