Files correlati : librerie Ricompilazione Demo : [ ] Commento : Corretta generazione bottoni di filtro sulle ricerche. Ora genera ID+500 invece di ID+1000 che causava sovrapposizioni agli ID delle colonne della griglia di ricerca git-svn-id: svn://10.65.10.50/trunk@14061 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1786 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1786 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #define XI_INTERNAL
 | |
| #include <xinclude.h>    
 | |
| 
 | |
| #include <colors.h>
 | |
| #include <config.h>
 | |
| #include <controls.h>
 | |
| #include <diction.h>
 | |
| #include <relation.h>
 | |
| #include <sheet.h>
 | |
| #include <urldefid.h>
 | |
| #include <utility.h>
 | |
| #include <xvtility.h>
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TSheet_control
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TSheet_control : public TControl
 | |
| {
 | |
|   enum { FIRST_FIELD = 101, MAX_COL = 256 };
 | |
| 
 | |
|   TSheet* _sheet;
 | |
|   long _cur_rec;
 | |
|   
 | |
|   // @cmember:(INTERNAL) Tipo di ogni colonna
 | |
|   byte _type[MAX_COL];
 | |
| 
 | |
|   // @cmember:(INTERNAL) Indica se e attivata la gestione dei check delle righe
 | |
|   bool _check_enabled;
 | |
| 
 | |
|   // @cmember:(INTERNAL) Array di righe attivate
 | |
|   TBit_array _checked;
 | |
| 
 | |
|   // @cmember:(INTERNAL) Array di righe disabilitate
 | |
|   TBit_array _disabled;  
 | |
|   
 | |
|   // @cmember:(INTERNAL) Array delle largezze standard
 | |
|   int _default_width[MAX_COL];
 | |
|   
 | |
|   byte _save_columns_order;
 | |
| 
 | |
| protected:  // TControl
 | |
|   //@cmember Gestisce gli eventi delle celle
 | |
|   virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev);
 | |
|   
 | |
| protected:  
 | |
|   long items() const { return _sheet->items(); }
 | |
|   TToken_string& row(long n) const { return _sheet->row(n); }
 | |
| 
 | |
|   int rec2row(long rec) const;
 | |
|   long row2rec(int row) const;
 | |
|   
 | |
|   void make_current(long rec);
 | |
|   XI_OBJ* find_column(int col) const;
 | |
|   XI_OBJ* find_column(const char* head) const;
 | |
| 
 | |
| public:  // TControl
 | |
|   virtual void set_rect(const RCT& r);
 | |
|   
 | |
| public:                   
 | |
|   long selected() const { return _cur_rec; }
 | |
|   void select(long n);
 | |
|   void set_focus_rec(long rec);
 | |
|   
 | |
|   void enable_check(bool on);
 | |
|   bool check_enabled() const { return _check_enabled; }
 | |
|   void check(long n, bool on);
 | |
|   void toggle(long n);
 | |
|   bool checked(long n) const { return _checked[n]; }
 | |
|   long checked() const { return _checked.ones(); }
 | |
|   bool one_checked() const;
 | |
|   
 | |
|   int visible_rows() const;
 | |
|   
 | |
|   void enable_row(long r, bool on);
 | |
|   void disable_row(long r);
 | |
|   bool row_enabled(long n) const { return _disabled[n] == FALSE; }
 | |
|   bool one_enabled() const { return _disabled.ones() < _sheet->items(); }
 | |
|   
 | |
|   byte column_type(int c) const { CHECKD(c >= 0 && c < MAX_COL, "Bad column ", c); return _type[c]; }
 | |
|   void align_column(int c, bool right);
 | |
| 
 | |
|   void set_columns_order(TToken_string* order);
 | |
|   void save_columns_order(const TMask_field& f) const;
 | |
|   void load_columns_order(const TMask_field& f);
 | |
|   
 | |
|   void update(long n = -1);
 | |
| 
 | |
|   TSheet_control(WINDOW sheet, short cid, short x, short y, short dx, short dy,              
 | |
|                  const char* flags, const char* head);
 | |
|   virtual ~TSheet_control() {}
 | |
| };
 | |
| 
 | |
| 
 | |
| TSheet_control::TSheet_control(
 | |
|   WINDOW parent,         // @parm Finestra alla quale appartiene lo spreadsheet
 | |
|   short cid,             // @parm Identificatore
 | |
|   short x,               // @parm Coordinata x (in caratteri) nel quale posizionare lo spreadsheet
 | |
|   short y,               // @parm Coordinata y (in caratteri) nel quale posizionare lo spreadsheet
 | |
|   short dx,              // @parm Larghezza (in caratteri) dello spreasheet
 | |
|   short dy,              // @parm Lunghezza (in caratteri) dello spreasheet
 | |
|   const char* flags,     // @parm Flags di abilitazione
 | |
|   const char* head)      // @parm Titolo delle colonne
 | |
|               : _sheet(NULL), _cur_rec(0), _check_enabled(FALSE), 
 | |
|                 _save_columns_order(FALSE)
 | |
|                 
 | |
| {
 | |
|   const int NUMBER_WIDTH = 7;
 | |
|   short v_width[MAX_COL];
 | |
|   short m_width[MAX_COL];
 | |
|   int fixed_columns = 1;                               // Number of fixed columns
 | |
|   int lines_in_cell = 1;
 | |
|   
 | |
|   _sheet = (TSheet*)xvt_vobj_get_data(parent);
 | |
|   
 | |
|   // Calcolo larghezza massima tabella
 | |
| 
 | |
|   TToken_string header(head);
 | |
|   TToken_string new_header(header.size());
 | |
|   int f_width = NUMBER_WIDTH;                          // Stima larghezza colonne fisse
 | |
|   int max_width = f_width;                             // Stima larghezza della colonna piu' grande
 | |
|   int lines_in_header = 1;
 | |
|   const char * h;
 | |
|   
 | |
|   int i = 0;
 | |
|   for (h = header.get(); h && i < MAX_COL; h = header.get(), i++)
 | |
|   {
 | |
|     _type[i] = ' ';
 | |
|     TString testa(h);
 | |
|     
 | |
|     char* t = testa.get_buffer();
 | |
|     for (int c = 0; t[c]; c++)
 | |
|     {
 | |
|       if (t[c] == '\\' && (t[c+1] == 'n' || t[c+1] == 'r'))
 | |
|       {
 | |
|         t[c] = '\n';
 | |
|         strcpy(t+c+1, t+c+2);
 | |
|       }
 | |
|       if (t[c] == '\n')
 | |
|         lines_in_header = 2;
 | |
|     }
 | |
|     
 | |
|     const int at = testa.rfind('@');
 | |
|     int v = testa.len();                             // Video width
 | |
|     if (at >= 0)
 | |
|     {
 | |
|       const TString& wi = testa.mid(at+1);
 | |
|       v = atoi(wi);
 | |
|       if (wi.find('F') >= 0) 
 | |
|       {
 | |
|         fixed_columns++;
 | |
|         f_width += v+1;
 | |
|       }    
 | |
|       if (wi.find('R') >= 0)
 | |
|         _type[i] = 'R'; else  
 | |
|       if (wi.find('V') >= 0)
 | |
|         _type[i] = 'V'; else
 | |
|       if (wi.find('P') >= 0)
 | |
|         _type[i] = 'P'; else
 | |
|       if (wi.find('M') >= 0)
 | |
|         _type[i] = 'M'; else
 | |
|       if (wi.find('C') >= 0)
 | |
|         _type[i] = 'C';
 | |
| 
 | |
|       if (i == 0 && v <= 1)
 | |
|       { 
 | |
|         _type[i] = 'C';
 | |
|         _check_enabled = TRUE;
 | |
|         fixed_columns++;
 | |
|         f_width += v+1;
 | |
|       }  
 | |
| 
 | |
|       testa.cut(at);
 | |
|       if (v == 0) v = at;
 | |
|     } 
 | |
|     
 | |
|     if (v > 64) 
 | |
|     {
 | |
|       lines_in_cell = (v-1) / 64 + 1;
 | |
|       v = 64;
 | |
|     }  
 | |
|     m_width[i] = v*lines_in_cell + 1; 
 | |
|     v_width[i] = v+1;
 | |
|     if (v > max_width) 
 | |
|       max_width = v;
 | |
|     
 | |
|     new_header.add(testa);
 | |
|   }
 | |
|   
 | |
|   // Calcola rettangolo massimo per lo sheet
 | |
|   RCT rct; coord2rct(parent, x, y, dx, dy, rct);
 | |
|   rct.right -= 2*XI_FU_MULTIPLE;           // toglie scroll-bar
 | |
|  
 | |
|   // Controlla se ci sono troppe colonne fisse
 | |
|   if ((f_width+max_width)*XI_FU_MULTIPLE > rct.right)
 | |
|     fixed_columns = 1;
 | |
|     
 | |
|   XI_OBJ* itf = get_interface(parent);     
 | |
| 
 | |
|   XI_OBJ_DEF* listdef = xi_add_list_def(NULL, cid,
 | |
|                                         rct.top, rct.left, rct.bottom-rct.top,
 | |
|                                         XI_ATR_ENABLED | XI_ATR_VISIBLE | XI_ATR_NAVIGATE,
 | |
|                                         NORMAL_COLOR, NORMAL_BACK_COLOR,     // normal
 | |
|                                         NORMAL_COLOR, DISABLED_BACK_COLOR,   // disabled
 | |
|                                         FOCUS_COLOR,                         // active
 | |
|                                         0);
 | |
|                                         
 | |
|   listdef->app_data = (long)this;
 | |
|   
 | |
|   XI_LIST_DEF* l = listdef->v.list;
 | |
| #ifdef XI_R4
 | |
|   l->min_heading_height = xi_button_calc_height_font(xi_get_system_font()) * lines_in_header;
 | |
| #else
 | |
|   l->min_heading_height = xi_button_calc_height_font_id(xvt_default_font()) * lines_in_header;
 | |
| #endif
 | |
|   l->max_lines_in_cell  = lines_in_cell;
 | |
|   l->sizable_columns    = TRUE;
 | |
|   l->movable_columns    = TRUE;
 | |
|   l->fixed_columns      = fixed_columns;
 | |
|   l->scroll_bar         = TRUE;                        
 | |
|   l->scroll_bar_button  = TRUE;
 | |
|   l->white_space_color  = MASK_DARK_COLOR;
 | |
|   l->rule_color         = MASK_DARK_COLOR;
 | |
| #ifdef LINUX
 | |
|   l->scroll_on_thumb_track = TRUE;
 | |
| #endif
 | |
| 
 | |
|   // Definizione della prima colonna (numero di riga)
 | |
|   const long attr = XI_ATR_VISIBLE | XI_ATR_RJUST | XI_ATR_SELECTABLE;                                            
 | |
|   XI_OBJ_DEF* coldef = xi_add_column_def(listdef, FIRST_FIELD+1000-1, attr, 0, 
 | |
|                                          2 * XI_FU_MULTIPLE, NUMBER_WIDTH , "");
 | |
|   
 | |
|   coldef->app_data = (long)this;
 | |
|   coldef->v.column->heading_platform = TRUE;
 | |
|   coldef->v.column->column_platform  = TRUE;
 | |
|   coldef->v.column->center_heading   = TRUE; 
 | |
| 
 | |
|   for (h = new_header.get(0), i = 0; h && i < MAX_COL; h = new_header.get(), i++)
 | |
|   {                  
 | |
|     long attr = XI_ATR_VISIBLE | XI_ATR_ENABLED | XI_ATR_AUTOSCROLL | XI_ATR_READONLY; 
 | |
|     if (_type[i] == 'C') 
 | |
|       attr |= XI_ATR_SELECTABLE;            
 | |
|     if (_type[i] == 'R' || _type[i] == 'V' || _type[i] == 'P')         // Right, Currency, Price
 | |
|       attr |= XI_ATR_RJUST;
 | |
|     coldef = xi_add_column_def(listdef, FIRST_FIELD+i+1000, attr, i+1, 
 | |
|                                v_width[i] * XI_FU_MULTIPLE, m_width[i], (char*)h);
 | |
| 
 | |
|     coldef->app_data = (long)this;
 | |
|     coldef->v.column->heading_platform = TRUE;
 | |
|     coldef->v.column->center_heading = TRUE;
 | |
|     if (m_width[i] > 64)
 | |
|       coldef->v.column->wrap_text = TRUE;
 | |
|     
 | |
|     if (i == 0 && _type[i] == 'C') 
 | |
|     {
 | |
|       coldef->v.column->icon_rid = ICO_CHECK_ON;
 | |
|       coldef->v.column->icon_mode = XIM_ICON_HAS_PRIORITY;
 | |
|       if (l->min_heading_height < 20)
 | |
|         l->min_heading_height = 20;
 | |
|     }
 | |
|   }
 | |
|                                 
 | |
|   RCT rd; xi_get_def_rect(listdef, (XinRect *) &rd);
 | |
|   if ((rd.right - rd.left) > (rct.right - rct.left))
 | |
|     l->width = rct.right - rct.left;
 | |
| 
 | |
|   _obj = xi_create(itf, listdef);     // Create the whole thing!
 | |
|   xi_dequeue();                       // Flush events in XOL
 | |
|   xi_tree_free(listdef);              // Free definitions
 | |
|                
 | |
|   CHECKD(_obj, "Can't create spreadsheet ", cid);   
 | |
|   update_tab_cid();
 | |
|   
 | |
|   // Se la finestra e' troppo grande riducila
 | |
|   RCT cli; xvt_vobj_get_client_rect(parent, &cli);
 | |
|   RCT xc = cli; xi_pu_to_fu(itf, (XinPoint *) &xc, 2);
 | |
|   if (xc.right > 45 * XI_FU_MULTIPLE)    // Deve contenere almeno 4 bottoni
 | |
|   {
 | |
|     xi_get_rect(_obj, (XinRect *) &rct);
 | |
|     
 | |
|     const int width = (rct.right-rct.left) + 2*XI_FU_MULTIPLE;
 | |
|     if (width < cli.right)
 | |
|     {
 | |
|       RCT out; xvt_vobj_get_outer_rect(parent, &out);
 | |
|       RCT rct; 
 | |
|       rct.left   = out.left + (cli.right - width) / 2;
 | |
|       rct.right  = rct.left + width;
 | |
| 	    rct.top    = out.top;   // cli had left = 0 and top = 0 
 | |
| 	    rct.bottom = rct.top + cli.bottom;
 | |
|       xvt_vobj_move(parent, &rct);
 | |
|     }
 | |
|   } 
 | |
|   
 | |
|   int num;
 | |
|   XI_OBJ** column = xi_get_member_list(_obj, &num);
 | |
|   for (i = 0; i < num; i++) 
 | |
|   {
 | |
|     RCT rct; xi_get_rect(column[i], (XinRect *) &rct);
 | |
|     _default_width[i] = rct.right - rct.left;
 | |
|   }
 | |
| } 
 | |
| 
 | |
| void TSheet_control::set_rect(const RCT& r)
 | |
| {
 | |
|   const int width  = r.right - r.left - 2*XI_FU_MULTIPLE;
 | |
|   const int height = r.bottom - r.top;
 | |
|   xi_set_list_size(_obj, height, width);
 | |
| }
 | |
| 
 | |
| // Converts a row number in the correspondig record number
 | |
| int TSheet_control::rec2row(long record) const
 | |
| {
 | |
|   int rows;
 | |
|   const long* rec = xi_get_list_info(_obj, &rows);
 | |
|   int r = int(record - rec[0]);
 | |
|   if (r < 0 || r >= rows) 
 | |
|     r = -1;
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Converts a row number in the correspondig record number
 | |
| long TSheet_control::row2rec(int row) const
 | |
| {
 | |
|   int rows;
 | |
|   const long* handle = xi_get_list_info(_obj, &rows);
 | |
|   
 | |
|   if (row < 0) 
 | |
|     row = 0;
 | |
|   else 
 | |
|   {
 | |
|     if (row >= rows) 
 | |
|       row = rows-1;
 | |
|   }    
 | |
|   const long r = handle[row];
 | |
|   CHECKD(r >= 0 && r < items(), "Sheet line out of range: ", row);
 | |
|   
 | |
|   return r;
 | |
| } 
 | |
| 
 | |
| int TSheet_control::visible_rows() const
 | |
| {
 | |
|   return xi_get_visible_rows(_obj, NULL, NULL);
 | |
| }
 | |
| 
 | |
| void TSheet_control::update(long n)
 | |
| {
 | |
|   if (n >= 0)
 | |
|   {
 | |
|     const int riga = rec2row(n);
 | |
|     if (riga >= 0)
 | |
|     {                 
 | |
|       XI_OBJ row;
 | |
|       XI_MAKE_ROW(&row, _obj, riga);
 | |
|       xi_cell_request(&row);           
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|  //   xi_cell_request(_obj);
 | |
|     int num = 0;
 | |
|     const long* handle = xi_get_list_info(_obj, &num);
 | |
| 
 | |
|     bool scroll_first = items() == 0; // || !owner().mask().is_running();
 | |
|     if (!scroll_first)
 | |
|     {
 | |
|       int first = 0, last = 0;
 | |
|       xi_get_visible_rows(_obj, &first, &last);   
 | |
|       n = handle[first];
 | |
|       scroll_first = n > items();
 | |
|     }
 | |
|     
 | |
|     if (scroll_first)
 | |
|       xi_scroll(_obj, XI_SCROLL_FIRST);
 | |
|     else
 | |
|       xi_scroll_rec(_obj, n, NORMAL_COLOR, XI_ATR_ENABLED, 0);
 | |
|   }  
 | |
| }
 | |
| 
 | |
| void TSheet_control::make_current(long rec)
 | |
| {               
 | |
|   const long old = _cur_rec;
 | |
|   _cur_rec = rec;
 | |
|   
 | |
|   XI_OBJ o; 
 | |
|   const int oldrow = rec2row(old);
 | |
|   if (oldrow >= 0)
 | |
|   {
 | |
|     XI_MAKE_ROW(&o, _obj, oldrow);
 | |
|     xi_cell_request(&o);
 | |
|   }  
 | |
|   const int newrow = rec2row(rec);
 | |
|   if (newrow >= 0 && newrow != oldrow)
 | |
|   {
 | |
|     XI_MAKE_ROW(&o, _obj, newrow);
 | |
|     xi_cell_request(&o);
 | |
|   }   
 | |
| }
 | |
| 
 | |
| void TSheet_control::select(long rec)
 | |
| {     
 | |
|   if (rec >= 0 && rec < items())
 | |
|   {
 | |
|     int rows;
 | |
|     const long* handle = xi_get_list_info(_obj, &rows);
 | |
|             
 | |
|     int first = 0, last = 0;
 | |
|     xi_get_visible_rows(_obj, &first, &last);
 | |
| 
 | |
|     if (rec < handle[first] || rec > handle[last])
 | |
|       xi_scroll_rec(_obj, rec, NORMAL_COLOR, XI_ATR_ENABLED, 0);
 | |
|   }  
 | |
|   make_current(rec);
 | |
| }
 | |
| 
 | |
| void TSheet_control::set_focus_rec(long rec)
 | |
| {
 | |
|   if (rec < 0) 
 | |
|     rec = selected();
 | |
|   int r = rec2row(rec);
 | |
|   if (r < 0)
 | |
|   {
 | |
|     select(rec);
 | |
|     r = rec2row(rec);
 | |
|   }                 
 | |
|   
 | |
|   const int c = _type[0] == 'C' ? 2 : 1;
 | |
|   XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, r, c);
 | |
|   xi_set_focus(&cell);
 | |
| }                                         
 | |
| 
 | |
| XI_OBJ* TSheet_control::find_column(
 | |
|   int col) const    // @parm  Indice o identificatore colonna
 | |
| {     
 | |
|   CHECKD(col >= 0, "Bad column ", col);
 | |
|   if (col < FIRST_FIELD)         // Se e' un indice trasformalo in identificatore
 | |
|     col += FIRST_FIELD + 1000;
 | |
|   
 | |
|   int num;
 | |
|   XI_OBJ** columns = xi_get_member_list(_obj, &num);
 | |
|   int c;
 | |
|   
 | |
|   for (c = num-1; c >= 0; c--)
 | |
|   {          
 | |
|     if (columns[c]->cid == col)
 | |
|       break;
 | |
|   }  
 | |
|   return c >= 0 ? columns[c] : NULL;
 | |
| }
 | |
| 
 | |
| XI_OBJ* TSheet_control::find_column(
 | |
|   const char* head) const    // @parm  testata colonna
 | |
| {     
 | |
|   int num;
 | |
|   XI_OBJ** column = xi_get_member_list(_obj, &num);
 | |
|   int c;
 | |
|   
 | |
|   for (c = num-1; c >= 0; c--)
 | |
|   {         
 | |
|     char str[80];     
 | |
|     xi_get_text(column[c], str, sizeof(str));
 | |
|     if (strcmp(str, head) == 0)
 | |
|       break;
 | |
|   }  
 | |
|   return c >= 0 ? column[c] : NULL;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void TSheet_control::enable_check(bool on)
 | |
| {
 | |
|   _check_enabled = on && _type[0] == 'C';
 | |
|   if (_type[0] == 'C')
 | |
|   {
 | |
|     XI_OBJ* column = find_column(1101);
 | |
|     CHECK(column, "Can't find checkable column");
 | |
|     dword attr = xi_get_attrib(column);
 | |
|     if (_check_enabled) attr |= XI_ATR_ENABLED;
 | |
|     else attr &= ~XI_ATR_ENABLED;
 | |
| 
 | |
|     xi_set_attrib(column, attr);          // Set new attributes
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool TSheet_control::one_checked() const
 | |
| {
 | |
|   bool yes = FALSE;
 | |
|   if (check_enabled())
 | |
|   {
 | |
|     const long first = _checked.first_one();
 | |
|     yes =  first >= 0;
 | |
|   }
 | |
|   return yes;
 | |
| }
 | |
| 
 | |
| // @mfunc Permette di attivare/disattivare una riga
 | |
| void TSheet_control::check(
 | |
|   long n,  // @parm Numero della riga da attivare/disattivare
 | |
|   bool on) // @parm Operazione da effettuare sulla riga:
 | |
|   //
 | |
|   // @flag TRUE | Attiva la riga <p n>.esima (default)
 | |
|   // @flag FALSE | Disattiva la riga <p n>.esima
 | |
| {
 | |
|   if (n < 0)
 | |
|   {
 | |
|     if (on)
 | |
|     {
 | |
|       const long tot = items()-1;
 | |
| 			if (tot >= 0)
 | |
| 			{
 | |
| 				_checked.set(tot);            // Forza le dimensioni del bit array
 | |
| 				_checked.set();               // Setta tutti i bit
 | |
|       
 | |
| 				// Elimina i bit in eccesso alla fine dell'array
 | |
| 				for (long i = _checked.items()-1; i > tot; i--)
 | |
| 					_checked.reset(i);
 | |
|       
 | |
| 				// Elimina i bit corrispondenti a righe disabilitate
 | |
| 				if (_disabled.first_one() >= 0)
 | |
| 				{ 
 | |
| 					for (long i = tot; i >= 0; i--)
 | |
| 						if (_disabled[i]) _checked.reset(i);
 | |
| 				}   
 | |
| 			}
 | |
|     } 
 | |
|     else
 | |
|       _checked.reset();
 | |
|     
 | |
|     // Aggiorna tutta la prima colonna
 | |
|     XI_OBJ* column = xi_get_obj(_obj, FIRST_FIELD+1000);
 | |
|     xi_cell_request(column);
 | |
|   }     
 | |
|   else           
 | |
|   {
 | |
|     if (!_disabled[n])
 | |
|     {
 | |
|       _checked.set(n, on);            
 | |
|       // Aggiorna la riga  
 | |
|       if (_sheet->is_running())
 | |
|       {
 | |
|         XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, rec2row(n), 1);
 | |
|         xi_cell_request(&cell);
 | |
|       }
 | |
|     }
 | |
|   }  
 | |
| }
 | |
| 
 | |
| void TSheet_control::toggle(long n)
 | |
| {
 | |
|   check(n, !checked(n));
 | |
| }
 | |
| 
 | |
| // @doc INTERNAL
 | |
| 
 | |
| // @mfunc Abilita/disabilita una riga
 | |
| void TSheet_control::enable_row(
 | |
|   long n,  // @parm Numero della riga da abilitare/diabilitare (default -1)
 | |
|   bool on) // @parm Operazione da svolgere sulla riga
 | |
|   //
 | |
|   // @flag TRUE | Abilita la riga <p n>-esima (default)
 | |
|   // @flag FALSE | Disabilita la riga <p n>-esima
 | |
| 
 | |
|   // @comm Se <p n> e' minore di 0 allora vengono abilitate/disabilitate tutte le righe
 | |
| {              
 | |
|   if (n >= 0)
 | |
|   {
 | |
|     _disabled.set(n, !on);
 | |
|   }  
 | |
|   else                     
 | |
|   {
 | |
|     if (on) 
 | |
|       _disabled.reset();
 | |
|     else
 | |
|     {
 | |
|       const long tot = items()-1;
 | |
|       _disabled.set(tot);      // Forza le dimensioni del bit-array
 | |
|       _disabled.set();         // Disabilita tutte le righe
 | |
|       
 | |
|       // Resetta i bit in ecesso alla fine del bit-array
 | |
|       for (long i = _disabled.items()-1; i > tot; i--)
 | |
|         _disabled.reset(i);
 | |
|     }
 | |
|   }  
 | |
|   update(n);
 | |
| }       
 | |
| 
 | |
| // Costruisce l'identificatore del paragrafo contenente la disposizione
 | |
| // delle colonne del campo f
 | |
| HIDDEN TFilename& field2parag(const TMask_field& f, TFilename& name)
 | |
| { 
 | |
|   const TMask& m = f.mask();
 | |
|   name = m.source_file();      
 | |
|   name.ext("");                // Nome della maschera senza estensione
 | |
|   const int index = m.number();
 | |
|   CHECKD(index >= 0 && index <= 8, "Bad mask index:", index);
 | |
|   if (index > 0)          // Aggiunge l'eventuale numero di sotto-maschera
 | |
|     name << '(' << index << ')';
 | |
|   return name;
 | |
| }
 | |
| 
 | |
| void TSheet_control::save_columns_order(const TMask_field& field) const
 | |
| {
 | |
|   if (_save_columns_order)
 | |
|   {
 | |
|     TFilename parag; field2parag(field, parag);
 | |
|     TConfig config(CONFIG_USER, parag);   // Apre il file di configurazione
 | |
| 
 | |
|     TToken_string order(127);             // Nuovo ordine delle colonne
 | |
|     if (_save_columns_order == TRUE)      // Se vale 3 devo solo resettare
 | |
|     {
 | |
|       int num;
 | |
|       XI_OBJ** column = xi_get_member_list(_obj, &num);
 | |
|       for (int i = 0; i < num; i++)       // Scorre tutte le colonne
 | |
|       {             
 | |
| 				TString h;
 | |
|         char head[80];
 | |
| 
 | |
|         xi_get_text(column[i], head, sizeof(head));
 | |
| 				for (const char * s = head; *s; s++)
 | |
| 				{
 | |
| 					if (*s == '\n')
 | |
| 						h << "\\n";
 | |
| 					else
 | |
| 						h << *s;
 | |
| 				}
 | |
|         order.add(h);
 | |
|         RCT rct; xi_get_rect(column[i], (XinRect *) &rct);
 | |
|         order << ',' << rct.right - rct.left;
 | |
|       }
 | |
|       config.set("Browse", order, NULL, TRUE, field.dlg());
 | |
|     }  
 | |
|     else
 | |
|       config.remove("Browse", field.dlg());
 | |
|   }  
 | |
| }
 | |
| 
 | |
| void TSheet_control::load_columns_order(const TMask_field& field)
 | |
| {
 | |
|   TFilename parag; field2parag(field, parag);
 | |
|   TConfig config(CONFIG_USER, parag);
 | |
|   const int index = field.dlg();
 | |
|   TToken_string order(esc(config.get("Browse", NULL, index)));
 | |
|   if (order.empty_items())
 | |
|     config.remove("Browse", index);
 | |
|   else
 | |
|     set_columns_order(&order);
 | |
|   
 | |
|   _save_columns_order = FALSE;  
 | |
| }                   
 | |
| 
 | |
| void TSheet_control::align_column(int c, bool right)
 | |
| {
 | |
|   XI_OBJ* column = find_column(c);
 | |
|   CHECKD(column, "Can't find numeric column ", c);
 | |
|   dword attr = xi_get_attrib(column);
 | |
|   if (right)
 | |
|     attr |= XI_ATR_RJUST;
 | |
|   else
 | |
|     attr &= ~XI_ATR_RJUST;
 | |
|   xi_set_attrib(column, attr);       
 | |
|   _type[c] = right ? 'R' : ' ';
 | |
| }
 | |
| 
 | |
| void TSheet_control::set_columns_order(TToken_string* order)
 | |
| {                                 
 | |
|   XI_OBJ* itf = get_interface();
 | |
|   XI_OBJ* focus = xi_get_focus(itf);
 | |
|   xi_set_focus(itf);
 | |
|   
 | |
|   int num_cols;
 | |
|   xi_get_member_list(_obj, &num_cols);  //verificare
 | |
|   
 | |
|   // Costante da sottrarre nella xi_column_set_pixel_width altrimenti la somma due volte!
 | |
|   const int offset = 2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
 | |
|   
 | |
|   if (order == NULL)
 | |
|   {
 | |
|     for (int index = 0; index < num_cols; index++)
 | |
|     {                                
 | |
|       const short cid = FIRST_FIELD + 1000 + index - 1;
 | |
|       XI_OBJ* col = find_column(cid);
 | |
|       if (col)
 | |
|       {
 | |
|         xi_move_column(col, index); 
 | |
|         RCT rct; xi_get_rect(col, (XinRect *) &rct);
 | |
|         if (_default_width[index] != rct.right - rct.left)
 | |
|           xi_column_set_pixel_width(col, _default_width[index]-offset);
 | |
|       }    
 | |
|     }  
 | |
|     _save_columns_order = 0x3;
 | |
|   }
 | |
|   else
 | |
|   {              
 | |
|     TString head(23);
 | |
|     TToken_string col(8, ',');
 | |
|     int pos = 0;
 | |
|     for (col = order->get(0); !col.blank(); col = order->get(), pos++)
 | |
|     {
 | |
|       head = col.get(0);
 | |
|       const int width = col.get_int();
 | |
|       XI_OBJ* column = find_column(head);
 | |
|       if (column)                        // Controlla che esista ancora
 | |
|       {             
 | |
|         if (pos > 0 && pos < num_cols)
 | |
|           xi_move_column(column, pos);   // Sposta la colonna se possibile
 | |
|         if (width > XI_FU_MULTIPLE)      // Se ha una larghezza valida
 | |
|           xi_column_set_pixel_width(column, width - offset);
 | |
|       }
 | |
|     }  
 | |
|   }
 | |
|   
 | |
|   if (focus)
 | |
|     xi_set_focus(focus);
 | |
| }
 | |
|        
 | |
| HIDDEN long _rec_to_select = -1;
 | |
| // Certified 75%
 | |
| bool TSheet_control::event_handler(XI_OBJ* itf, XI_EVENT *xiev)
 | |
| {
 | |
|   BOOLEAN& refused = xiev->refused;   
 | |
| 
 | |
|   switch (xiev->type)
 | |
|   {
 | |
|   case XIE_GET_FIRST:
 | |
|     if (items() > 0L)
 | |
|     {
 | |
|       long n = items() * (long)xiev->v.rec_request.percent / 100L;
 | |
|       if (n < 0L) n = 0L;
 | |
|       xiev->v.rec_request.data_rec = n;
 | |
|     }
 | |
|     else
 | |
|       refused = TRUE;
 | |
|     break;
 | |
|   case XIE_GET_LAST:
 | |
|     xiev->v.rec_request.data_rec = items()-1;
 | |
|     break;
 | |
|   case XIE_GET_PREV:
 | |
|   case XIE_GET_NEXT:
 | |
|   {
 | |
|     const long n = xiev->v.rec_request.spec_rec + (xiev->type == XIE_GET_NEXT ? +1 : -1) ;
 | |
|     if (n < 0 || n >= items())
 | |
|       refused = TRUE;
 | |
|     else
 | |
|       xiev->v.rec_request.data_rec = n;
 | |
|   }
 | |
|     break;
 | |
|   case XIE_CELL_REQUEST:
 | |
|   {
 | |
|     const long rec = xiev->v.cell_request.rec;
 | |
|     const char* src = NULL;
 | |
|     int nm;
 | |
|     XI_OBJ** obj = xi_get_member_list(xiev->v.cell_request.list, &nm);
 | |
|     const int num = xiev->v.cell_request.col_nbr;
 | |
|     const int cid = obj[num]->cid - 1000;
 | |
| 
 | |
|     if (cid >= FIRST_FIELD)
 | |
|     {
 | |
|       if (rec >= 0 && rec < items())
 | |
|       { 
 | |
|         const int col = cid - FIRST_FIELD;
 | |
|         switch (_type[col])
 | |
|         {
 | |
|         case 'C':                                 // Set value for "checkable" cell
 | |
|           {
 | |
|             const bool on = checked(rec);
 | |
|             xiev->v.cell_request.icon_rid = on ? ICO_CHECK_ON : ICO_CHECK_OFF;
 | |
|           }  
 | |
|           break;
 | |
|         case 'M':                                 // Set value for "roman" cell
 | |
|           src = itor(atoi(row(rec).get(col)));    
 | |
|           break;
 | |
|         case 'V':                                 // Set value for "value" cell
 | |
|           {                                      
 | |
|             const real r = row(rec).get(col);
 | |
|             TCurrency c(r);
 | |
|             src = c.string(TRUE);    
 | |
|           }
 | |
|           break;
 | |
|         case 'P':                                 // Set value for "price" cell
 | |
|           {                                      
 | |
|             const real r = row(rec).get(col);
 | |
|             TPrice c(r);
 | |
|             src = c.string(TRUE);    
 | |
|           }
 | |
|           break;
 | |
|         default:                                  // Set value for "normal" cell
 | |
|           src = row(rec).get(col);                
 | |
|           break;
 | |
|         }  
 | |
| 
 | |
|         if (_disabled[rec])
 | |
|         {
 | |
|           xiev->v.cell_request.color = NORMAL_COLOR; 
 | |
|           xiev->v.cell_request.back_color = DISABLED_BACK_COLOR; 
 | |
|         } 
 | |
|         else
 | |
|           if (rec == _cur_rec)
 | |
|           {                                                
 | |
|             xiev->v.cell_request.color = FOCUS_COLOR; 
 | |
|             xiev->v.cell_request.back_color = FOCUS_BACK_COLOR; 
 | |
|           }
 | |
|           else
 | |
|             _sheet->get_cell_colors(rec, col, xiev->v.cell_request.color, xiev->v.cell_request.back_color); 
 | |
|       }  
 | |
|       else
 | |
|         refused = TRUE;
 | |
|     } 
 | |
|     else
 | |
|     { 
 | |
|       xiev->v.cell_request.color = NORMAL_COLOR; 
 | |
| //      src = format("%ld", rec+1);   // Niente piu' numeri di riga!
 | |
|     } 
 | |
| 
 | |
|     char* dst = xiev->v.cell_request.s;
 | |
|     if (src && *src)
 | |
|     {
 | |
|       const int len = xiev->v.cell_request.len;
 | |
|       strncpy(dst, src, len);
 | |
|       dst[len-1] = '\0';
 | |
|     }  
 | |
|     else
 | |
|       *dst = '\0';
 | |
|   }
 | |
|     break;
 | |
|   case XIE_DBL_CELL:
 | |
|     {
 | |
|       const long rec = row2rec(xiev->v.xi_obj->v.cell.row);
 | |
|       if (!_disabled[rec])
 | |
|       {
 | |
|         make_current(rec);
 | |
|         _sheet->stop_run(K_ENTER);
 | |
|       }
 | |
|       else
 | |
|         refused = TRUE;
 | |
|     }  
 | |
|     break;   
 | |
|   case XIE_ON_LIST:    
 | |
|     _sheet->notify_focus_field(id());
 | |
|     break;
 | |
|   case XIE_ON_ROW:
 | |
|     {            
 | |
|       const long rec = row2rec(xiev->v.xi_obj->v.row);
 | |
|       if (_disabled[rec])
 | |
|       {
 | |
|         refused = TRUE;
 | |
|         // Cerca la prossima riga abilitata e valida
 | |
|         const int dir = rec > selected() ? +1: -1;
 | |
|         const long max = items();
 | |
|         for (long r = rec+dir; r >= 0 && r < max; r += dir) if (!_disabled[r])
 | |
|         {
 | |
|           _sheet->post_select(r);
 | |
|           break;
 | |
|         }    
 | |
|       }  
 | |
|       else                    
 | |
|       {
 | |
|         if (_sheet->_select_row < 0)
 | |
|           make_current(rec);
 | |
|         else 
 | |
|           _rec_to_select = rec;
 | |
|       }
 | |
|     }
 | |
|     break;
 | |
|   case XIE_GET_PERCENT:
 | |
|   {
 | |
|     const long rec = xiev->v.get_percent.record;
 | |
|     long n = items(); if (n <= 0) n = 1;
 | |
|     xiev->v.get_percent.percent = int(rec * 100L / n);
 | |
|   }
 | |
|     break;
 | |
|   case XIE_SELECT:
 | |
|     if (xiev->v.xi_obj->type == XIT_ROW)
 | |
|     {           
 | |
|       const int row = xiev->v.select.xi_obj->v.row;
 | |
|       const long rec = row2rec(row);
 | |
|       if (row_enabled(rec))
 | |
|       {
 | |
|         int num;
 | |
|         XI_OBJ** column = xi_get_member_list(_obj, &num);
 | |
|         const int col = xiev->v.select.column;
 | |
|       
 | |
|         const short cid = column[col]->cid - 1000;
 | |
|         if (cid >= FIRST_FIELD)
 | |
|         { 
 | |
|           if (check_enabled())
 | |
|             toggle(rec);
 | |
|         }
 | |
|         else 
 | |
|         {
 | |
|           if (_cur_rec == rec)
 | |
|             _sheet->on_key(K_CTRL+'G'); 
 | |
|         }
 | |
|         const int c = _type[0] == 'C' ? 2 : 1;
 | |
|         XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, row, c);
 | |
|         xi_set_focus(&cell);
 | |
|         make_current(rec);
 | |
|       }
 | |
|     }  
 | |
|     refused = TRUE;
 | |
|     break;  
 | |
|   case XIE_COL_MOVE:           
 | |
|     if (xiev->v.column.in_fixed || 
 | |
|         xiev->v.column.col_nbr < xi_get_fixed_columns(xiev->v.column.list))
 | |
|       refused = TRUE;
 | |
|     else
 | |
|       _save_columns_order = TRUE;
 | |
|     break;  
 | |
|   case XIE_COL_SIZE:            
 | |
|     {
 | |
|       if (_obj->v.list->hsb_win) 
 | |
|         _save_columns_order = TRUE;
 | |
|       else
 | |
|         refused = TRUE;  // Non permetto il resize in assenza di scroll bar orizzontale
 | |
|     }
 | |
|     break;  
 | |
|   case XIE_BUTTON:
 | |
|     if (xiev->v.xi_obj->type == XIT_LIST)
 | |
|       _sheet->on_key(K_CTRL+'N');
 | |
|     break;         
 | |
|   case XIE_XVT_EVENT:
 | |
|     if (xiev->v.xvte.type == E_CHAR)
 | |
|     {
 | |
|       const KEY k = e_char_to_key(&xiev->v.xvte);
 | |
|       long rec = -1;
 | |
|       switch (k)
 | |
|       {                         
 | |
| 
 | |
|         case K_SPACE: 
 | |
|           if (_check_enabled)
 | |
|             check(selected(), !checked(selected()));
 | |
|           break;
 | |
|         case K_ENTER:
 | |
|           if (_disabled[_cur_rec])
 | |
|             break;
 | |
|         case K_ESC:
 | |
|           _sheet->stop_run(k);
 | |
|           break;
 | |
|         case K_LHOME:                                      
 | |
|           rec = 0; 
 | |
|           break;
 | |
|         case K_PREV: 
 | |
|           rec = _cur_rec - visible_rows(); 
 | |
|           if (rec < 0) rec = 0; 
 | |
|           break;
 | |
|         case K_NEXT: 
 | |
|           rec = _cur_rec + visible_rows(); 
 | |
|           if (rec >= items())
 | |
|             rec = items()-1;
 | |
|           break;
 | |
|         case K_LEND:  
 | |
|           rec = items()-1; 
 | |
|           break;
 | |
|         default:     
 | |
|           break;
 | |
|       }
 | |
|       if (rec >= 0) 
 | |
|       {
 | |
|         _sheet->post_select(rec);
 | |
|         refused = TRUE;
 | |
|       }  
 | |
|     }  
 | |
|     break;  
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
|   
 | |
|   return !refused;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////               
 | |
| // TQuery_field
 | |
| ///////////////////////////////////////////////////////////               
 | |
| 
 | |
| class TQuery_field : public TOperable_field
 | |
| {                       
 | |
| protected:
 | |
|   virtual void create(WINDOW parent);
 | |
| 
 | |
| public:                      
 | |
|   TSheet_control* sheet() const { return (TSheet_control*)_ctl; }
 | |
| 
 | |
|   TQuery_field(TMask* m) : TOperable_field(m) { }
 | |
|   virtual ~TQuery_field() { }
 | |
| };
 | |
| 
 | |
| void TQuery_field::create(WINDOW parent)
 | |
| { 
 | |
|   _ctl = new TSheet_control(parent, dlg(), 
 | |
|                             _ctl_data._x, _ctl_data._y, 
 | |
|                             _ctl_data._width, _ctl_data._size, 
 | |
|                             _ctl_data._flags, _ctl_data._prompt);
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////               
 | |
| // TSheet
 | |
| ///////////////////////////////////////////////////////////               
 | |
| 
 | |
| #define DLG_QUERY 25883
 | |
|            
 | |
| TSheet::TSheet(short x, short y, short dx, short dy,
 | |
|                const char* title, const char* head, 
 | |
|                byte buttons, short sht_y, WINDOW parent)
 | |
|       : TMask(title, sht_y == 0 ? 1 : 2, dx, dy, x, y, parent), 
 | |
|         _sheet(NULL), _select_row(-1), _parked(-1)
 | |
| {                                         
 | |
|   TQuery_field* qf = new TQuery_field(this);
 | |
|   qf->construct(DLG_QUERY, head, 1, sht_y, -3, win(), "", -1);
 | |
|   fields_array().add(qf);
 | |
|   _sheet = qf->sheet();
 | |
| 
 | |
|   if (!(buttons & 0x10)) add_button(DLG_SELECT, TR("~Selezione"), K_ENTER);
 | |
|   if (check_enabled())   
 | |
|   {
 | |
|     add_button(DLG_USER, TR("~Tutti"), 0);
 | |
|     set_handler(DLG_USER, tutti_handler);
 | |
|   }  
 | |
| 
 | |
|   if (buttons & 0x01) add_button(DLG_LINK,   TR("Colle~ga"), K_CTRL+'G', BMP_LINK);
 | |
|   if (buttons & 0x02) add_button(DLG_NEWREC, TR("~Nuovo"), K_INS, BMP_NEWREC, BMP_NEWRECDN);
 | |
|   if (buttons & 0x04) add_button(DLG_DELREC, "", K_DEL);
 | |
|   if (buttons & 0x08) add_button(DLG_QUIT,   "", K_ESC);
 | |
|   else                add_button(DLG_CANCEL, "", K_ESC);
 | |
| }
 | |
| 
 | |
| TSheet::~TSheet()
 | |
| {
 | |
| //  delete _sheet;   // Guy bestia:  Already deleted by TMask!
 | |
| }
 | |
| 
 | |
| TSheet_control& TSheet::sheet()
 | |
| { return *_sheet; }
 | |
| 
 | |
| // @doc INTERNAL
 | |
| 
 | |
| // @mfunc Aggiunge un bottone nella finestra
 | |
| void TSheet::add_button(
 | |
|   short id,              // @parm Identificatore del bottone da aggiungere
 | |
|   const char* caption,   // @parm Testo del bottone da aggiungere
 | |
|   KEY key,               // @parm Combinazione di tasti corrispondente
 | |
|   short bmp_up,          // @parm Bitmap normale
 | |
|   short bmp_dn)          // @parm Bitmap premuta
 | |
| {         
 | |
|   TButton_field& butt = TMask::add_button(id, 0, caption, 0, -1, 11, 2, 
 | |
|                                           "", bmp_up, bmp_dn);
 | |
|   butt.set_exit_key(key);
 | |
| }
 | |
| 
 | |
| bool TSheet::get_cell_colors(int row, int col, COLOR& fore, COLOR& back) const 
 | |
| { 
 | |
|   fore = back = 0;   // Default colors
 | |
|   return false;      // Not assigned
 | |
| }  
 | |
| 
 | |
| void TSheet::repos_buttons() const
 | |
| {      
 | |
|   if (_sheet == NULL)
 | |
|     return;                  // Sono ancora in fase di creazione: aspetta!
 | |
| 
 | |
|   RCT br;
 | |
|   int buttons = 0, f;
 | |
|   for (f = fields()-1; f >= 0; f--)
 | |
|   {                     
 | |
|     TMask_field& c = fld(f);
 | |
|     if (c.is_kind_of(CLASS_BUTTON_FIELD))
 | |
|     {
 | |
|       if (buttons == 0) 
 | |
|         c.get_rect(br);
 | |
|       buttons++;
 | |
|     } 
 | |
|   }
 | |
|   
 | |
|   RCT wr; xvt_vobj_get_client_rect(win(), &wr);
 | |
|   const short width = br.right - br.left;
 | |
|   const short height = br.bottom - br.top;
 | |
|     
 | |
|   int space = (wr.right - buttons * width) / (buttons+1);
 | |
|   if (space < 0) space = 0;
 | |
|   int x = space;
 | |
|   const int y = wr.bottom - height - XI_FU_MULTIPLE;
 | |
| 
 | |
|   for (f = 0; buttons > 0; f++)
 | |
|   {                                    
 | |
|     TMask_field& c = fld(f);
 | |
|     if (c.is_kind_of(CLASS_BUTTON_FIELD))
 | |
|     {                  
 | |
|       buttons--;
 | |
|       const PNT p = { y, x };
 | |
|       xvt_rect_set_pos(&br, p);
 | |
|       c.set_rect(br);
 | |
|       x += space+width;
 | |
|     }  
 | |
|   }  
 | |
| }
 | |
| 
 | |
| void TSheet::force_update(int r)
 | |
| {
 | |
|   _sheet->update(r);
 | |
| }
 | |
| 
 | |
| void TSheet::start_run()
 | |
| {                          
 | |
|   const bool on = items() > 0 && _sheet->one_enabled();
 | |
| 
 | |
|   // Abilita selezione se c'e' almeno un elemento
 | |
|   int pos = id2pos(DLG_SELECT);
 | |
|   if (pos >= 0)
 | |
|     fld(pos).enable(on);     
 | |
|     
 | |
|   pos = id2pos(DLG_LINK);
 | |
|   if (pos >= 0)
 | |
|     fld(pos).enable(on);     
 | |
|     
 | |
|   reset_parked();
 | |
|     
 | |
|   repos_buttons();
 | |
|   force_update();
 | |
|   
 | |
|   if (on)      
 | |
|   {
 | |
|     long i = selected();
 | |
|     if (i < 0 || i >= items())
 | |
|       i = 0;                   
 | |
|     if (row_disabled(i))
 | |
|       for (i = 0; row_disabled(i); i++);
 | |
|     post_select(i);
 | |
|   }  
 | |
| }
 | |
| 
 | |
| long TSheet::selected() const
 | |
| { return _sheet->selected(); }
 | |
| 
 | |
| bool TSheet::check_enabled() const
 | |
| { return _sheet->check_enabled(); }
 | |
| 
 | |
| void TSheet::enable_check(bool on)
 | |
| { _sheet->enable_check(on); }
 | |
| 
 | |
| void TSheet::check(long n, bool on)
 | |
| { _sheet->check(n, on); }
 | |
| 
 | |
| bool TSheet::checked(long n) const
 | |
| { return _sheet->checked(n); }
 | |
| 
 | |
| long TSheet::checked() const
 | |
| { return _sheet->checked(); }
 | |
| 
 | |
| bool TSheet::one_checked() const
 | |
| { return _sheet->one_checked(); }
 | |
| 
 | |
| void TSheet::enable_row(long r, bool on)
 | |
| { _sheet->enable_row(r, on); }
 | |
| 
 | |
| bool TSheet::row_enabled(long r) const
 | |
| { return _sheet->row_enabled(r); }
 | |
|       
 | |
| bool TSheet::on_key(KEY key)
 | |
| {
 | |
|   switch(key)
 | |
|   {
 | |
|   case K_ESC:
 | |
|     stop_run(key);
 | |
|     break;
 | |
|   case K_CTRL+'E':
 | |
|   case K_DEL:
 | |
|     if (items() && id2pos(DLG_DELREC) >= 0)
 | |
|       stop_run(K_DEL);
 | |
|     break;
 | |
|   case K_CTRL+'N':
 | |
|     if (id2pos(DLG_NEWREC) >= 0)
 | |
|       stop_run(K_INS);
 | |
|     break;
 | |
|   case K_CTRL+'G':
 | |
|     if (id2pos(DLG_LINK) >= 0)
 | |
|       stop_run(key);
 | |
|     break;
 | |
|   case K_CTRL+'S':
 | |
|     if (id2pos(DLG_SELECT) >= 0)
 | |
|       stop_run(K_ENTER);
 | |
|     break;  
 | |
|   default: 
 | |
|     key -= K_CTRL;            
 | |
|     if (key >= 'A' && key <= 'Z')
 | |
|     {
 | |
|       for (int i = fields()-1; i >= 0; i--)
 | |
|       {
 | |
|         TMask_field& f = fld(i);
 | |
|         if (f.active() && f.is_kind_of(CLASS_BUTTON_FIELD))
 | |
|         {
 | |
|           TButton_field& b = (TButton_field&)f;
 | |
|           if (b.virtual_key() == key)
 | |
|           {             
 | |
|             f.on_key(K_SPACE);
 | |
|             if (b.exit_key() > 0)
 | |
|               stop_run(b.exit_key());
 | |
|             return TRUE;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   if (check_enabled() && items() > 0)
 | |
|   { 
 | |
|     switch(key)
 | |
|     {
 | |
| //    case K_SPACE: 
 | |
| //      check(selected(), !checked(selected()));
 | |
| //      break;
 | |
|     case K_CTRL+'T':
 | |
|       tutti_handler(field(DLG_USER), K_SPACE);
 | |
|       break;
 | |
|     case K_F7: 
 | |
|       uncheck(-1); 
 | |
|       break;
 | |
|     case K_F8:   
 | |
|       check(-1);
 | |
|       break;
 | |
|     default: 
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // @doc INTERNAL
 | |
| 
 | |
| // @mfunc Seleziona una riga facendola diventare corrente
 | |
| void TSheet::select(
 | |
|   long n)  // @parm Riga da selezionare
 | |
| {
 | |
|   _sheet->select(n);
 | |
| }
 | |
| 
 | |
| void TSheet::post_select(long rec)
 | |
| {
 | |
|   _select_row = rec;
 | |
| }
 | |
| 
 | |
| void TSheet::on_idle()
 | |
| {
 | |
|   if (_select_row >= 0)
 | |
|   {    
 | |
|     const short focus_id = low_get_focus_id(win());  
 | |
|     _sheet->select(_select_row);
 | |
|     if (focus_id == _sheet->id())
 | |
|       _sheet->set_focus_rec(-1);
 | |
|     _select_row = -1;
 | |
|   }
 | |
|   TMask::on_idle();
 | |
| }
 | |
| 
 | |
| // @doc INTERNAL
 | |
| 
 | |
| // @mfunc Ritorna il contenuto di una riga
 | |
| //
 | |
| // @rdesc Ritorna la <c TToken_string> con tutti gli elemnti della riga
 | |
| TToken_string& TSheet::row(
 | |
|   long n)  // @parm Riga di cui ritorna il contenuto (default -1)
 | |
| 
 | |
|   // @comm Se viene passato un numero di riga minore di 1 viene ritornato il contenuto della riga
 | |
|   //   selezionata.
 | |
| {
 | |
|   if (n < 0) n = selected();
 | |
|   if (n != _parked)
 | |
|     get_row(_parked = n, _park);
 | |
|   return _park;
 | |
| }
 | |
| 
 | |
| bool TSheet::tutti_handler(TMask_field& f, KEY k)
 | |
| {
 | |
|   if (k == K_SPACE)
 | |
|   {       
 | |
|     TSheet& s = (TSheet&)f.mask();
 | |
| 		if (s.check_enabled())
 | |
| 			s.check(-1, !s.one_checked());
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TArray_sheet
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TArray_sheet::TArray_sheet(short x, short y, short dx, short dy, const char* caption, 
 | |
|                            const char* head, byte buttons, short sht_y)
 | |
|             : TSheet(x, y, dx, dy, caption, head, buttons, sht_y)
 | |
| { 
 | |
|   if (dx == 0)
 | |
|   {
 | |
|     TToken_string cap(caption);
 | |
|     add_tag_buttons(cap);
 | |
|   }  
 | |
| }
 | |
| 
 | |
| // Certified 99%
 | |
| bool TArray_sheet::destroy(int i)               
 | |
| {
 | |
|   uncheck(-1);
 | |
|   enable_row(-1); 
 | |
|   reset_parked();
 | |
|   return _data.destroy(i, TRUE);
 | |
| }                                                             
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Aggiunge un elemento allo sheet
 | |
| //
 | |
| // @rdesc Ritorna il numero di elementi presenti nello sheet
 | |
| long TArray_sheet::add( 
 | |
|   const TToken_string& s)  // @parm Oggetto da aggiungere
 | |
|   // @parm const TToken_string | *s | Oggetto da aggiungere passato per indirizzo
 | |
| 
 | |
|   // @syntax add(const TToken_string& s)
 | |
|   // @syntax add(const TToken_string* s)
 | |
| {
 | |
|   const long n = _data.add(s);
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| long TArray_sheet::add(TToken_string* s)
 | |
| {
 | |
|   const long n = _data.add(s);
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| long TArray_sheet::insert(const TToken_string& s, long n)
 | |
| {
 | |
|   _data.insert(s, (int)n);
 | |
|   const int maxrows=int(items());
 | |
|   for (int r = maxrows-1; r >n ; r--)
 | |
|   {
 | |
|     const bool enab= row_enabled(r);
 | |
|     enable_row(r,row_enabled(r+1));
 | |
|     enable_row(r+1,enab);
 | |
|   }
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TCursor_sheet
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| bool TCursor_sheet::in_key(const TFieldref& fr) const
 | |
| {
 | |
|   const int logic = _cursor->file().num();
 | |
|   if (fr.file() != 0 && fr.file() != logic)
 | |
|     return false;
 | |
| 
 | |
|   const RecDes& rd = prefix().get_recdes(logic);
 | |
| 
 | |
|   const int key = _cursor->key();
 | |
|   const KeyDes& kd = rd.Ky[key-1];
 | |
| 
 | |
|   for (int i = 0; i < kd.NkFields; i++)
 | |
|   {
 | |
|     const int n = kd.FieldSeq[i] % MaxFields;
 | |
|     if (strcmp(rd.Fd[n].Name, fr.name()) == 0)
 | |
|       return true;
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| TCursor_sheet::TCursor_sheet(TCursor* cursor, const char* fields,
 | |
|                              const char* title, const char* head, 
 | |
|                              byte buttons, short sht_y, WINDOW parent)
 | |
|              : TSheet(sht_y ? 3 : 0, sht_y ? 3 : 0, sht_y ? -3 : 0, sht_y ? -3 : 0, 
 | |
|                       title, head, buttons, sht_y, parent), _cursor(cursor)
 | |
| {
 | |
|   TToken_string fldlst(fields);
 | |
|   int campo = 0;
 | |
|   for (const char* t = fldlst.get(0); t; t = fldlst.get(), campo++)
 | |
|   {
 | |
|     if (*t > ' ' && *t != '"')
 | |
|     {
 | |
|       const TFieldref fr(t, 0);
 | |
|       TRecfield* rf = new TRecfield(_cursor->curr(fr.file()),
 | |
|                                     fr.name(), fr.from(), fr.to() - 1);
 | |
|       _fields.add(rf, campo);
 | |
|       
 | |
|       const TFieldtypes tipo = rf->type();       
 | |
|       if (tipo == _intfld || tipo == _longfld || tipo == _realfld)
 | |
|       {
 | |
|         byte c = sheet().column_type(campo);
 | |
|         if (c == ' ') 
 | |
|           sheet().align_column(campo, TRUE);
 | |
|       }  
 | |
| 
 | |
|       _key_cols.set(campo, in_key(fr));
 | |
|     }
 | |
|   }  
 | |
| }
 | |
| 
 | |
| HIDDEN bool _can_post = FALSE;
 | |
| 
 | |
| KEY TCursor_sheet::run()
 | |
| {
 | |
|   _cursor->freeze(TRUE);
 | |
| 
 | |
|   select(_cursor->pos());
 | |
|   _can_post = TRUE;
 | |
|   
 | |
|   const KEY k = TSheet::run();
 | |
|   _cursor->freeze(FALSE);
 | |
|   return k;
 | |
| }
 | |
| 
 | |
| long TCursor_sheet::get_items() const
 | |
| { return _cursor ? _cursor->items() : 0; }
 | |
| 
 | |
| void TCursor_sheet::get_row(long row, TToken_string& l)
 | |
| {
 | |
|   *_cursor = (TRecnotype)row;
 | |
|   l.cut(0);
 | |
|   const int last = _fields.last();
 | |
|   for (int i = 0; i <= last; i++)
 | |
|   {
 | |
|     const TRecfield* rf = (TRecfield*)_fields.objptr(i);
 | |
|     const char* s = rf ? (const char*)*rf : "";
 | |
|     l.add(s);
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool TCursor_sheet::get_cell_colors(int row, int col, COLOR& fore, COLOR& back) const
 | |
| {
 | |
|   if (_key_cols[col])
 | |
|   {
 | |
|     fore = 0;
 | |
|     back = REQUIRED_BACK_COLOR;
 | |
|     return true;
 | |
|   }
 | |
|   return TSheet::get_cell_colors(row, col, fore, back);
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TBrowse_sheet
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| HIDDEN TBrowse_sheet* _cur_browse = NULL;
 | |
| 
 | |
| void TBrowse_sheet::add_custom_filter(const char* regexp)
 | |
| {
 | |
|   TString filter = _original_filter; // Costruisco il nuovo filtro per estensione del vecchio
 | |
|   if (regexp && *regexp)
 | |
|   {
 | |
|     if (_original_filter.not_empty())
 | |
|     {
 | |
|       filter.insert("(");
 | |
|       filter << ")&&(";
 | |
|     }
 | |
|     filter << regexp;
 | |
|     if (_original_filter.not_empty())
 | |
|       filter << ')';
 | |
|   }
 | |
| 
 | |
|   TCursor& c = *cursor();
 | |
|   if (filter != c.filter()) // Cambio il filtro se necessario :-)
 | |
|   {
 | |
|     c.freeze(false);
 | |
|     c.setfilter(filter, true);
 | |
|     c.items();            // Forzo la ricostruzione del cursore
 | |
|     c.freeze(true);
 | |
|     
 | |
|     // Forzo un aggiornamento a basso livello
 | |
|     TQuery_field& qf = (TQuery_field&)TMask::field(DLG_QUERY);
 | |
|     XI_OBJ* obj = qf.sheet()->xi_object();
 | |
|     xi_scroll_percent(obj, 100);
 | |
|     xi_scroll_percent(obj, 0);
 | |
| 
 | |
|     _sel = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool TBrowse_sheet::browse_field_handler(TMask_field& f, KEY k)
 | |
| {
 | |
|   long rec = -1;
 | |
|   
 | |
|   if (k == K_F2)
 | |
|   {
 | |
|     f.reset();
 | |
|     k = K_SPACE;
 | |
|   }
 | |
|   
 | |
|   if (k == K_SPACE)
 | |
|   {                                           
 | |
|     TEdit_field& e = _cur_browse->field();   // Campo padre dello sheet
 | |
|     TMask& m = e.mask();                     // Maschera che contiene lo sheet
 | |
|     TMask_field& c = m.field(f.dlg());       // Campo corrispondente sulla maschera
 | |
|     
 | |
|     // Ricopia su campo maschera
 | |
|     if (f.is_edit())
 | |
|     {
 | |
|       TEdit_field& ef = (TEdit_field&)f;
 | |
|       const TString& wd = ef.get_window_data();
 | |
|       c.set(wd);
 | |
|     }
 | |
|     else
 | |
|       c.set(f.get());                          
 | |
|     
 | |
|     TBrowse* b = e.browse();
 | |
|     if (b != NULL)
 | |
|     {
 | |
|       b->do_input(FALSE);
 | |
|       rec = b->cursor()->read(_isgteq);
 | |
|     }  
 | |
|   }
 | |
| 
 | |
|   if (rec >= 0 && rec != _cur_browse->selected())
 | |
|   {
 | |
|     _cur_browse->select(rec);        // Non mettere post_select
 | |
|     _can_post = TRUE;
 | |
|     
 | |
|     RCT r; f.get_rect(r);
 | |
|     xvt_dwin_invalidate_rect(f.parent(), &r);  // Non ricordo a cosa serva aggiornare il campo di testo
 | |
|   }  
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TBrowse_sheet::last_browse_field_handler(TMask_field& f, KEY k)
 | |
| {
 | |
|   const bool ok = browse_field_handler(f, k);
 | |
|   if (ok) 
 | |
|   {       
 | |
|     if (k == K_TAB && _can_post)
 | |
|     {
 | |
|       _cur_browse->post_select(_cur_browse->selected());
 | |
|       _can_post = FALSE;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       if (k == K_CTRL+K_TAB)
 | |
|       {
 | |
|         RCT r; f.get_rect(r);
 | |
|         xvt_dwin_invalidate_rect(f.parent(), &r);
 | |
|       }  
 | |
|     }
 | |
|   }  
 | |
|   
 | |
|   return ok;  
 | |
| }
 | |
| 
 | |
| bool TBrowse_sheet::filter_handler(TMask_field& f, KEY k)
 | |
| {
 | |
|   if (k == K_SPACE)
 | |
|   {
 | |
|     TString expr;                  // Espressione di filtro complessiva
 | |
|     if (!f.get().empty())          // Filtro attivato!
 | |
|     {
 | |
|       const short id = f.dlg()-500;
 | |
|       TString e = f.mask().get(id);  // Espressione regolare
 | |
|       e.strip("\"'");                // Tolgo caratteri che potrebbero dare problemi  
 | |
|       if (!e.blank())
 | |
|       {
 | |
|         const TBrowse& b = *_cur_browse->field().browse();
 | |
|         TToken_string ids = b.get_input_fields();
 | |
|         const int pos = ids.get_pos(id);
 | |
|         if (pos >= 0)
 | |
|         {
 | |
|           TToken_string fns = b.get_input_field_names();
 | |
|           expr << fns.get(pos) << "?=\"" << e << '"';
 | |
|         }
 | |
|       }
 | |
|       if (expr.empty())
 | |
|         f.reset();
 | |
|     }
 | |
|     _cur_browse->add_custom_filter(expr);
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Gestisce l'handler della finestra
 | |
| void TBrowse_sheet::handler(
 | |
|   WINDOW win, // @parm Finestra da gestire
 | |
|   EVENT* ep)  // @parm Evento da gestire nella finestra
 | |
| {                 
 | |
|   if (ep->type == E_MOUSE_DOWN)
 | |
|   {   
 | |
|     TSheet_control& sht = sheet();
 | |
|     switch (ep->v.mouse.button )
 | |
|     {      
 | |
|     case  1: 
 | |
|       { 
 | |
|         MENU_ITEM* menu = xvt_res_get_menu(BROWSE_BAR);
 | |
|         if (menu)
 | |
|         {         
 | |
| 					dictionary_translate_menu(menu);
 | |
|           const PNT& p = ep->v.mouse.where;
 | |
|           RCT cr; xvt_vobj_get_client_rect(win, &cr);
 | |
|           XVT_POPUP_ALIGNMENT pa = XVT_POPUP_CENTER;
 | |
|           if (p.h < cr.right / 3)
 | |
|             pa = XVT_POPUP_LEFT_ALIGN;
 | |
|           else
 | |
|             if (p.h > 2 * cr.right / 3)
 | |
|               pa = XVT_POPUP_RIGHT_ALIGN;
 | |
|             
 | |
|           xvt_menu_popup(menu->child, win, p, pa, NULL);
 | |
|           xvt_res_free_menu_tree(menu);       
 | |
|         }  
 | |
|         return;
 | |
|       }
 | |
|       break;
 | |
|     default:
 | |
|       {
 | |
|         RCT r; sht.get_rect(r);
 | |
|         if (xvt_rect_has_point(&r, ep->v.mouse.where) && _rec_to_select >= 0)
 | |
|         {
 | |
|           post_select(_rec_to_select);
 | |
|           _rec_to_select = -1;     
 | |
|         }
 | |
|       }  
 | |
|       break;
 | |
|     }  
 | |
|   }                   
 | |
|   else
 | |
|   if (ep->type == E_COMMAND)
 | |
|   {
 | |
|     switch (ep->v.cmd.tag)
 | |
|     {     
 | |
|     case BROWSE_BAR + 1:
 | |
|       sheet().save_columns_order(field());
 | |
| 			return;
 | |
|     case BROWSE_BAR + 2:
 | |
|       sheet().set_columns_order(NULL);
 | |
|       return;
 | |
|     case BROWSE_BAR + 3:
 | |
|       fld(0).on_key(K_F11);
 | |
|       return;
 | |
|     default:
 | |
|       break;  
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   TCursor_sheet::handler(win, ep);
 | |
| }
 | |
| 
 | |
| TBrowse_sheet::TBrowse_sheet(TCursor* cursor, const char* fields,
 | |
|                              const char* title, const char* head, byte buttons, 
 | |
|                              TEdit_field* f, TToken_string& sibling)
 | |
|              : TCursor_sheet(cursor, fields, title, head, buttons, 
 | |
|                              f->browse() ? f->browse()->input_fields() : 1), 
 | |
|                _field(f), _sel(0), _original_filter(cursor->filter())
 | |
| {
 | |
|   TBrowse* browse = f->browse();
 | |
|   if (browse == NULL)
 | |
|     return;
 | |
| 
 | |
|   TToken_string ca;         // Tag buttons
 | |
|   int n = 0;
 | |
|   for (const char* s = sibling.get(0); s && *s; s = sibling.get(), n++)
 | |
|   { 
 | |
|     const short id = f->atodlg(s);
 | |
|     const char* pr = sibling.get();
 | |
|     if (id == f->dlg())
 | |
|     {
 | |
|       _sel = n;
 | |
|     }  
 | |
|     ca.add(pr);
 | |
|   }                       
 | |
|   if (n > 0)
 | |
|     add_tag_button(0, ca, _sel);
 | |
|   
 | |
|   TToken_string tids = head;
 | |
|   TToken_string tfns = fields;                                       
 | |
|   TToken_string ids  = browse->get_input_fields();   
 | |
|   TToken_string fns  = browse->get_input_field_names();  
 | |
|   
 | |
|   TEditable_field* e = NULL;
 | |
|   short y  = 0;
 | |
| 	bool first = true;
 | |
| 
 | |
|   for (const char* i = ids.get(0); i; i = ids.get())
 | |
|   {                                     
 | |
|     if (*i != '"' && strchr(i, '@') == NULL)
 | |
|     {
 | |
|       const TMask_field& c = f->mask().field(f->atodlg(i));
 | |
|       if (c.is_editable() && c.active())
 | |
|       { 
 | |
|         int pos = ids.get_pos(c.dlg());
 | |
|         CHECK(pos >= 0, "Invalid input field");
 | |
|         TString80 p = fns.get(pos);
 | |
|         pos = tfns.get_pos(p);
 | |
|         if (pos >= 0)
 | |
|         {
 | |
|           p = tids.get(pos);
 | |
|           pos = p.find('@');
 | |
|           if (pos >= 0) 
 | |
|             p.cut(pos);
 | |
|         }  
 | |
|         else 
 | |
|           p.cut(0);
 | |
|       
 | |
|         if (p.empty())
 | |
|         {
 | |
|           p = c.prompt();
 | |
|           int a; 
 | |
|           // Toglie spazi e simboli iniziali dal prompt
 | |
|           for (a = 0; p[a] && !isalnum(p[a]); a++);
 | |
|           p.ltrim(a); 
 | |
|         }  
 | |
|         p.left_just(16);
 | |
|         
 | |
|         TString8 flags;
 | |
|         if (c.roman()) flags << 'M';
 | |
|         if (c.right_justified()) flags << 'R';
 | |
|         if (c.uppercase()) flags << 'U';
 | |
|         if (c.zerofilled()) flags << 'Z';
 | |
|         
 | |
|         const int csize = c.size();
 | |
|         
 | |
|         switch (c.class_id())
 | |
|         {
 | |
|         case CLASS_EDIT_FIELD:
 | |
|           {
 | |
|             const int sz = csize > 50 ? 50 : csize; // Dimensione del campo di ricerca
 | |
|             e = &add_string(c.dlg(), 0, p, 1, y++, csize, flags, sz);
 | |
|             // Aggiunge campo con le icone di filtraggio
 | |
|             add_checkbutton(c.dlg()+500, 0, "", sz+18, y-1, 2, 1, "", 10112, 10113).set_handler(filter_handler);         
 | |
|           }
 | |
|           break;
 | |
|         case CLASS_ZOOM_FIELD:
 | |
|           {
 | |
|             e = &add_string(c.dlg(), 0, p, 1, y++, 32000, flags, 50);
 | |
|             // Aggiunge campo con le icone di filtraggio
 | |
|             add_checkbutton(c.dlg()+500, 0, "", 68, y-1, 2, 1, "", 10112, 10113).set_handler(filter_handler);         
 | |
|           }
 | |
|           break;
 | |
|         case CLASS_REAL_FIELD:  
 | |
|           e = &add_number(c.dlg(), 0, p, 1, y++, csize, flags);
 | |
|           break;
 | |
|         case CLASS_DATE_FIELD:  
 | |
|           e = &add_date  (c.dlg(), 0, p, 1, y++, flags);
 | |
|           break;
 | |
|         default:
 | |
|           e = NULL;
 | |
|           break;
 | |
|         }    
 | |
|         if (e)
 | |
|         {
 | |
|           e->set_handler(browse_field_handler);
 | |
|           e->set(c.get());
 | |
|           if (e->dlg() == f->dlg() || first)
 | |
| 					{
 | |
|             first_focus(e->dlg());
 | |
| 						first = false;
 | |
| 					}
 | |
|         }
 | |
|       }
 | |
|     }    
 | |
|   }     
 | |
|   
 | |
|   if (e != NULL)
 | |
|     e->set_handler(last_browse_field_handler);
 | |
|     
 | |
|   sheet().load_columns_order(field());
 | |
| }
 | |
| 
 | |
| bool TBrowse_sheet::on_key(KEY k)
 | |
| {
 | |
|   if (k >= K_CTRL+K_F1 && k < K_CTRL+K_F10)
 | |
|   {            
 | |
|     const int what = k - K_CTRL - K_F1;
 | |
|     if (what >= 0 && what != _sel)
 | |
|       TWindow::stop_run(k);
 | |
|     return TRUE;  
 | |
|   }
 | |
|   return TSheet::on_key(k);
 | |
| }
 | |
| 
 | |
| KEY TBrowse_sheet::run()
 | |
| {       
 | |
|   _cur_browse = this;
 | |
|   
 | |
|   const KEY key = TCursor_sheet::run();
 | |
|   _cur_browse = NULL;
 | |
|   return key;
 | |
| }
 | |
| 
 | |
| 
 |