campo-sirio/ba/ba8301.cpp
guy 7e9576ecef Patch level : 2.1 48
Files correlati     : ba8
Ricompilazione Demo : [ ]
Commento            :

Aggiornamenti vari sui report


git-svn-id: svn://10.65.10.50/trunk@12110 c028cbd2-c16b-5b4b-a496-9718f37d4682
2004-05-24 12:50:35 +00:00

938 lines
21 KiB
C++
Executable File

#include <xinclude.h>
#include <statbar.h>
#include <diction.h>
#include <image.h>
#include <mask.h>
#include "ba8300.h"
#include "ba8301.h"
///////////////////////////////////////////////////////////
// TReport_tree
///////////////////////////////////////////////////////////
bool TReport_tree::get_description(TString& str) const
{
const char type = _curr[0];
const int level = atoi(_curr.mid(1));
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 (type == 'H' || type == 'F')
{
if (level <= 1)
str << TR("Report");
else
str << TR("Gruppo") << ' ' << (level-1);
}
else
str << level;
}
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;
}
TReport_section& TReport_tree::curr_section() const
{
char type = _curr[0];
const int level = _curr[1]-'0';
if (type == 'R' || type == 'P')
type = 'B';
return _report.section(type, level);
}
bool TReport_tree::goto_root()
{
return goto_node('P', 0);
}
bool TReport_tree::goto_firstson()
{
char ntype = 'H';
int nlevel = -1;
switch (_curr[0])
{
case 'P':
nlevel = 0;
break;
case 'R':
nlevel = 1;
break;
default : break;
}
return goto_node(ntype, nlevel);
}
bool TReport_tree::goto_rbrother()
{
const char type = _curr[0];
const int level = _curr[1]-'0';
char ntype = ' ';
int nlevel = -1;
if (level <= 0) // Page
{
switch (type)
{
case 'H': ntype = 'B'; break;
case 'B': ntype = 'F'; break;
case 'P': ntype = 'R'; break;
default : break;
}
nlevel = level;
}
else // Report
{
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)
{
return goto_node(id[0], id[1]-'0');
}
bool TReport_tree::has_son() const
{
bool yes = false;
switch (_curr[0])
{
case 'P':
case 'R':
yes = true;
break;
default:
break;
}
return yes;
}
bool TReport_tree::has_rbrother() const
{
const TString4 old = _curr;
TReport_tree* myself = (TReport_tree*)this;
const bool ok = myself->goto_rbrother();
myself->_curr = old;
return ok;
}
bool TReport_tree::has_root() const
{
return true; // In realta' ci sono 3 root: Pagina, Report, Speciali
}
bool TReport_tree::has_father() const
{
return !has_son();
}
bool TReport_tree::goto_father()
{
bool yes = has_father();
if (yes)
{
const char ntype = _curr[1] == '0' ? 'P' : 'R';
yes = goto_node(ntype, 0);
}
return yes;
}
bool TReport_tree::has_lbrother() const
{
const TString4 old = _curr;
TReport_tree* myself = (TReport_tree*)this;
const bool ok = myself->goto_lbrother();
myself->_curr = old;
return ok;
}
bool TReport_tree::goto_lbrother()
{
const char type = _curr[0];
const int level = _curr[1]-'0';
char ntype = ' ';
int nlevel = -1;
if (level == 0) // Page
{
switch (type)
{
case 'B': ntype = 'H'; break;
case 'F': ntype = 'B'; break;
case 'R': ntype = 'P'; break;
default : break;
}
nlevel = level;
}
else // Report
{
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;
case 'B': id = 1811; break;
case 'F': id = 1812; break;
default : break;
}
if (id > 0)
return get_res_image(id);
return TTree::image(selected);
}
int TReport_tree::image_height() const
{
const TImage* img = image(false);
return img != NULL ? img->height() : 0;
}
///////////////////////////////////////////////////////////
// TReport_window
///////////////////////////////////////////////////////////
class TReport_window : public TField_window
{
TReport* _report;
PNT _dpi;
int _dragging;
TPoint _pt_drag_start;
PNT _pt_drag_offset;
RCT _rct_drag;
TArray _clipboard;
protected:
virtual void handler(WINDOW win, EVENT* ep);
virtual void update();
virtual bool on_key(KEY k);
protected:
void draw_grid();
void snap_drag(PNT& pnt) const;
void draw_dragster();
void draw_field(const TReport_field& rf);
void draw_broken_paper(const TReport_field& rf);
void popup_menu(EVENT* ep);
void popup_cut();
void popup_copy();
void popup_paste();
int cpi() const;
int lpi() const;
public:
virtual PNT log2dev(long x, long y) const;
virtual TPoint dev2log(const PNT& pt) const;
TReport_section& curr_section() const;
bool get_selection_rect(TRectangle& rct) const;
bool pick(const TPoint& ptlog) const;
void clear_selection();
void select(const TRectangle& rct);
void offset_selection(const TPoint& p);
void set_report(TReport* rep) { _report = rep; }
TReport_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner);
virtual ~TReport_window() { }
};
TReport_section& TReport_window::curr_section() const
{
TMask& m = owner().mask();
TTree_field& sections = m.tfield(F_SECTIONS);
sections.goto_selected();
TReport_tree& tree = *(TReport_tree*)sections.tree();
return tree.curr_section();
}
bool TReport_window::pick(const TPoint& ptlog) const
{
TReport_section& rs = curr_section();
FOR_EACH_ARRAY_ITEM(rs, i, o)
{
TReport_field& f = *(TReport_field*)o;
const TRectangle& 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);
}
}
bool TReport_window::get_selection_rect(TRectangle& rct) const
{
TReport_section& rs = curr_section();
bool full = false;
FOR_EACH_ARRAY_ITEM(rs, i, o)
{
const TReport_field& f = *(const TReport_field*)o;
if (f.selected())
{
const TRectangle& fr = f.get_rect();
if (!full)
{
rct = fr;
full = true;
}
else
rct.merge(fr);
}
}
return full;
}
void TReport_window::offset_selection(const TPoint& p)
{
TReport_section& rs = curr_section();
FOR_EACH_ARRAY_ITEM(rs, i, o)
{
TReport_field& f = *(TReport_field*)o;
if (f.selected())
f.offset(p);
}
}
void TReport_window::select(const TRectangle& rct)
{
clear_selection();
TReport_section& rs = curr_section();
FOR_EACH_ARRAY_ITEM(rs, i, o)
{
TReport_field& f = *(TReport_field*)o;
if (rct.intersects(f.get_rect()))
f.select();
}
}
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_drag(PNT& pnt) const
{
const int kx = _dpi.h / cpi();
const int ky = _dpi.v / lpi();
pnt.h = (pnt.h / kx) * kx;
pnt.v = (pnt.v / ky) * ky;
}
bool TReport_window::on_key(KEY k)
{
switch (k)
{
case K_ENTER:
owner().mask().send_key(K_SPACE, F_FLD_PROPERTIES);
break;
case K_ESC:
{
TReport_section& rs = curr_section();
FOR_EACH_ARRAY_ITEM(rs, i, o)
{
TReport_field& f = *(TReport_field*)o;
if (f.selected())
f.select(false);
}
force_update();
}
break;
default:
break;
}
return TField_window::on_key(k);
}
#define POPUP_CUT 20883
#define POPUP_COPY 20884
#define POPUP_PASTE 20885
#define POPUP_DUP 20886
#define POPUP_CLEAR 20887
#define POPUP_PROPERTIES 20888
#define POPUP_NEWFIELD 20889
void TReport_window::popup_menu(EVENT* ep)
{
MENU_ITEM menu[16]; // Stiamo larghi
memset(menu, 0, sizeof(menu));
TRectangle rct;
const bool sel = get_selection_rect(rct);
const bool clp = _clipboard.items() > 0;
menu[0].tag = POPUP_CUT; menu[0].text = "Taglia"; menu[0].enabled = sel;
menu[1].tag = POPUP_COPY; menu[1].text = "Copia"; menu[1].enabled = sel;
menu[2].tag = POPUP_PASTE; menu[2].text = "Incolla"; menu[2].enabled = clp;
menu[3].tag = POPUP_DUP; menu[3].text = "Duplica"; menu[3].enabled = sel;
menu[4].tag = POPUP_CLEAR; menu[4].text = "Cancella"; menu[4].enabled = sel;
menu[5].tag = -1; menu[5].separator = true;
menu[6].tag = POPUP_PROPERTIES; menu[6].text = "Proprieta'"; menu[6].enabled = true;
menu[7].tag = POPUP_NEWFIELD; menu[7].text = "Nuovo"; menu[7].enabled = true;
const PNT& p = ep->v.mouse.where;
_pt_drag_start = dev2log(p);
xvt_menu_popup(menu, win(), p, XVT_POPUP_CENTER, 0);
}
void TReport_window::popup_cut()
{
_clipboard.destroy();
TReport_section& rs = curr_section();
FOR_EACH_ARRAY_ITEM_BACK(rs, i, o)
{
TReport_field& f = *(TReport_field*)o;
if (f.selected())
{
TObject* obj = rs.remove(i, true);
_clipboard.add(obj);
}
}
force_update();
}
void TReport_window::popup_copy()
{
_clipboard.destroy();
TReport_section& rs = curr_section();
FOR_EACH_ARRAY_ITEM(rs, i, o)
{
TReport_field& f = *(TReport_field*)o;
if (f.selected())
_clipboard.add(f);
}
}
void TReport_window::popup_paste()
{
if (_clipboard.items() > 0)
{
const TRectangle& rct = ((TReport_field&)_clipboard[0]).get_rect();
const TPoint off(_pt_drag_start.x-rct.left(), _pt_drag_start.y-rct.top());
clear_selection();
TReport_section& rs = curr_section();
FOR_EACH_ARRAY_ITEM(_clipboard, i, o)
{
const TReport_field& oldf = *(TReport_field*)o;
TReport_field* newf = new TReport_field(oldf);
newf->set_section(&rs);
newf->set_font(oldf.font()); // Font is section dependent!
newf->select();
newf->offset(off);
rs.add(newf);
}
force_update();
}
}
void TReport_window::handler(WINDOW win, EVENT* ep)
{
switch (ep->type)
{
case E_MOUSE_DOWN:
if (ep->v.mouse.button == 0)
{
const TPoint pt = dev2log(ep->v.mouse.where);
TRectangle rct;
bool full = get_selection_rect(rct);
if (!full || !rct.contains(pt))
{
if (full)
clear_selection();
pick(pt);
full = get_selection_rect(rct);
}
if (full)
{
TWindow::log2dev(rct, _rct_drag);
_pt_drag_offset.h = ep->v.mouse.where.h - _rct_drag.left;
_pt_drag_offset.v = ep->v.mouse.where.v - _rct_drag.top;
_dragging = 2;
XinCursor hand = xi_get_pref(XI_PREF_HAND_CURSOR_RID);
xvt_win_set_cursor(win, (CURSOR)hand);
}
else
{
const PNT& pnt = ep->v.mouse.where;
xvt_rect_set(&_rct_drag, pnt.h, pnt.v, pnt.h, pnt.v);
_dragging = 1;
}
_pt_drag_start.x = rct.left();
_pt_drag_start.y = rct.top();
draw_dragster();
xvt_win_trap_pointer(win);
}
else
{
popup_menu(ep);
}
break;
case E_MOUSE_MOVE:
{
TMask& m = owner().mask();
const TPoint p = dev2log(ep->v.mouse.where);
if (true) // Needs an option?
{
TString16 str; str.format("r:%3d c:%3d", p.y/100, p.x/100);
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;
if (!ep->v.mouse.shift)
snap_drag(pt);
xvt_rect_set_pos(&_rct_drag, pt);
break;
default:
break;
}
draw_dragster();
}
}
break;
case E_MOUSE_UP:
if (_dragging != 0)
{
draw_dragster();
PNT pt = ep->v.mouse.where;
switch (_dragging)
{
case 1:
{
_rct_drag.right = pt.h;
_rct_drag.bottom = pt.v;
TRectangle rct; TWindow::dev2log(_rct_drag, rct);
select(rct);
}
break;
case 2:
{
pt.h -= _pt_drag_offset.h; pt.v -= _pt_drag_offset.v;
if (!ep->v.mouse.shift)
snap_drag(pt);
TPoint offset = dev2log(pt);
offset.x -= _pt_drag_start.x;
offset.y -= _pt_drag_start.y;
offset_selection(offset);
}
break;
default:
break;
}
force_update();
_dragging = 0;
xvt_win_release_pointer();
xvt_win_set_cursor(win, CURSOR_ARROW);
}
break;
case E_MOUSE_DBL:
owner().mask().send_key(K_SPACE, F_FLD_PROPERTIES);
break;
case E_COMMAND:
switch(ep->v.cmd.tag)
{
case POPUP_CUT:
case POPUP_CLEAR:
popup_cut();
break;
case POPUP_COPY:
popup_copy();
break;
case POPUP_PASTE:
popup_paste();
break;
case POPUP_DUP:
popup_copy();
popup_paste();
break;
case POPUP_PROPERTIES:
{
clear_selection();
const bool full = pick(_pt_drag_start);
if (full)
owner().mask().send_key(K_SPACE, F_FLD_PROPERTIES);
else
owner().mask().send_key(K_SPACE, F_SEC_PROPERTIES);
}
break;
case POPUP_NEWFIELD:
owner().mask().send_key(K_SPACE, F_FLD_ADD);
break;
default:
break;
}
break;
default:
break;
}
TField_window::handler(win, ep);
}
PNT TReport_window::log2dev(long x, long y) const
{
x -= origin().x * 100L;
y -= 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;
}
void TReport_window::draw_grid()
{
clear(COLOR_WHITE);
const int max = 196;
const int k = 100;
for (int i = 1; i < max; i++)
{
set_pen(i%10 ? MAKE_COLOR(232,232,255) : MAKE_COLOR(255,192,255));
line(0, i*k, max*k, i*k);
line(i*k, 0, i*k, max*k);
}
}
void TReport_window::draw_broken_paper(const TReport_field& rf)
{
set_pen(COLOR_LTGRAY);
const TRectangle& 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)
{
RCT r; TWindow::log2dev(rf.get_rect(), r);
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(*this, rf.border(), rf.fore_color(), rf.back_color()))
xvt_dwin_draw_oval(win(), &r);
back_pattern = PAT_HOLLOW;
break;
case 'I':
{
TVariant var;
_report->evaluate(rf.field(), var, _alfafld);
const TString& name = var.as_string();
const TImage* img = _report->image(name);
if (img != NULL && img->ok())
img->draw(win(), r);
advanced_draw_rect(*this, r, rf.border(), rf.fore_color(), COLOR_WHITE);
}
break;
case 'L':
if (advanced_set_draw_tools(*this, rf.border(), rf.fore_color(), COLOR_WHITE))
{
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(*this, r, rf.border(), rf.fore_color(), rf.back_color());
break;
case 'T':
advanced_draw_rect(*this, r, rf.border(), rf.fore_color(), rf.back_color());
xvt_dwin_set_font(win(), rf.font().get_xvt_font(*this));
set_color(rf.fore_color(), rf.back_color());
advanced_draw_text(*this, rf.picture(), r, rf.horizontal_alignment(), rf.vertical_alignment());
break;
default :
if (rf.dynamic_height())
draw_broken_paper(rf);
else
{
if (rf.border() <= 0) // Rendi piu' visibile il bordo dei campi che non ce l'hanno
advanced_draw_rect(*this, r, 1, COLOR_LTGRAY, COLOR_WHITE);
else
advanced_draw_rect(*this, r, rf.border(), rf.fore_color(), rf.back_color());
}
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.fore_color(), rf.back_color());
}
TString str;
if (rf.id() > 0)
str << rf.id();
else
str = rf.field();
advanced_draw_text(*this, 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(*this, 0, COLOR_WHITE, COLOR_LTGRAY);
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::update()
{
draw_grid(); // Disegna griglia
const TReport_section& rs = curr_section();
int y = rs.height();
const bool is_dynamic = y <= 0; // Sezione ad altezza variabile
for (int i = 0; i < rs.items(); i++)
{
const TReport_field& rf = rs.field(i);
draw_field(rf);
if (is_dynamic)
{
const int fy = rf.get_rect().bottom();
if (fy > y) y = fy;
}
}
if (y > 0) // Disegna barra di fine sezione
{
if (is_dynamic)
{
const int mod = y % 100;
if (mod != 0) y += 100-mod;
}
hide_pen();
set_brush(COLOR_LTGRAY, PAT_DIAGCROSS);
bar(0, y, 19600, 6600);
}
}
int TReport_window::cpi() const
{ return _report ? _report->cpi() : 12; }
int TReport_window::lpi() const
{ return _report ? _report->lpi() : 6; }
TReport_window::TReport_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner)
: TField_window(x, y, dx, dy, parent, owner), _dragging(0), _report(NULL)
{
_dpi.h = _dpi.v = 96;
_pixmap = true;
set_scroll_max(196,196);
}
///////////////////////////////////////////////////////////
// TReport_drawer
///////////////////////////////////////////////////////////
TField_window* TReport_drawer::create_window(int x, int y, int dx, int dy, WINDOW parent)
{
return new TReport_window(x, y, dx, dy, parent, this);
}
void TReport_drawer::set_report(TReport* rep)
{
TReport_window* w = (TReport_window*)_win;
w->set_report(rep);
}