git-svn-id: svn://10.65.10.50/branches/R_10_00@22899 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			2148 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2148 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);
 | |
|     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 && !o.empty())
 | |
|     {
 | |
|       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)
 | |
| { 
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // 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 F_PRESCRIPT:
 | |
|   case F_POSTSCRIPT:
 | |
|     if (e == fe_close && !o.empty())
 | |
|     {
 | |
|       if (_report.prescript().starts_with(":"))
 | |
|         _report.compile_prescript(); // Compila eventuali nuove word
 | |
|     }
 | |
|     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("EL", 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();
 | |
|       if (name.find(".png") > 0)
 | |
|       {
 | |
|         TFilename n(name); 
 | |
|         if (n.custom_path())    
 | |
|           xvt_dwin_draw_image_on_pdf(win(), n, &r);
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         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();
 | |
| }
 |